Introduction
Socket is an interface between an application process and transport layer. The application process can send or receive messages to/from another application process (local or Network) through a socket. Winsock is the lowest level Windows API for TCP/IP programming. Part of the code is located in winsock.dll and the rest is inside the Windows kernel. In this article I shall try to explain how we can create a server and a client using winsock.
Background
Before going to the main topic I am trying to explain where the socket exists in different network layer.
Code:
Server Client
---------------------- ----------------------
| Application layer | | Application layer |
User Space | | User Space | |
+--------------------+ +--------------------+
| Socket | | Socket |
| | | |
+--------------------+ +--------------------+
| Transport layer | | Transport layer |
| | | |
| | | | | | | |
| | | |
Kernel Space | Network layer | Kernel Space | Network layer |
| | | |
| | | | | | | |
| | | |
| Link layer | | Link layer |
| | | |
| | | | | | | |
| | | |
| Physical layer | | Physical layer |
---------------------- ----------------------
to call for making this client server connection.
Code:
Server Client
----------------- -----------------
| WSAStartup() | | WSAStartup() |
+---------------+ +---------------+
| | | |
+---------------+ +---------------+
| socket() | | socket() |
+---------------+ +---------------+
| | | |
+---------------+ | |
| bind() | | |
+---------------+ | |
| | | |
+---------------+ +---------------+
| listen() | <----------- | connect() |
+---------------+ +---------------+
| | | |
+---------------+ | |
| accept() | | |
+---------------+ | |
| | | |
+---------------+ +---------------+
| send() | -----------> | recv() |
| | | |
| recv() | <----------- | send() |
+---------------+ +---------------+
| | | |
+---------------+ +---------------+
| closesocket() | | closesocket() |
+---------------+ +---------------+
| | | |
+---------------+ +---------------+
| WSACleanup() | | WSACleanup() |
----------------- -----------------
The socket() function creates a socket.
The bind() function bind a previously created socket to a specified socket address.
listen() begin listening on the port specified by the previous bind() call.
Server programcall accept() immediately after calling Listen(). accept() returns when a client connects to the socket, sending back a new socket that corresponds to the new connection.
The client program calls connect() after creating socket. Connect returns when the connection has been made.
The send() and recv() are for sending/receiving data to/from socket.
The closesocket() function closes an existing socket.
WSACleanup() terminates to use of socket dll.
The following code will create a server which will communicate with clients.
The code
Code:
#include <stdio.h>
#include <windows.h>
#include <winsock.h>
#define SOCKET_OK 0
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShow)
{
WORD sockVer;
WSADATA wsaData;
int retVal;
sockVer = MAKEWORD(2,2);
WSAStartup(sockVer, &wsaData);
/// Creating socket
SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(servSock == INVALID_SOCKET)
{
MessageBox(NULL, "Unable to create socket()", "SOCKET ERROR", MB_OK);
WSACleanup();
return SOCKET_ERROR;
}
/// Filling in sockaddr_in struct
SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons(1111);
sin.sin_addr.s_addr = INADDR_ANY;
retVal = bind(servSock, (LPSOCKADDR)&sin, sizeof(sin));
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to bind", "SOCKET ERROR", MB_OK);
WSACleanup();
return SOCKET_ERROR;
}
/// Trying to listen socket
retVal = listen(servSock, 10);
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to listen()", "SOCKET ERROR", MB_OK);
WSACleanup();
return SOCKET_ERROR;
}
/// Waiting for a client
SOCKET clientSock;
clientSock = accept(servSock, NULL, NULL);
if(clientSock == INVALID_SOCKET)
{
MessageBox(NULL, "Unable to accept()", "SOCKET ERROR", MB_OK);
WSACleanup();
return SOCKET_ERROR;
}
char szReq[8];
retVal = recv(clientSock, szReq, 8, 0);
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to recv()", "SOCKET ERROR", MB_OK);
return SOCKET_ERROR;
}
MessageBox(NULL, szReq, "Got the request from client", MB_OK);
char *szResp = "Response";
MessageBox(NULL, szResp, "Sending response from server", MB_OK);
retVal = send(clientSock, szResp, strlen(szResp), 0);
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to send()", "SOCKET ERROR", MB_OK);
return SOCKET_ERROR;
}
/// Closing socket
closesocket(clientSock);
closesocket(servSock);
WSACleanup();
return SOCKET_OK;
}
Code: Cpp
#include <windows.h>
#include <winsock.h>
int WINAPI WinMain(HINSTANCE hHinst, HINSTANCE hPrevHinst, LPSTR lpCmdLine,
int nShow)
{
WORD ver = MAKEWORD(2,2);
WSADATA wsaData;
int retVal=0;
WSAStartup(ver,(LPWSADATA)&wsaData);
LPHOSTENT hostEnt;
/// Collect information of the server
hostEnt = gethostbyname("Myxp");
if(!hostEnt)
{
MessageBox(NULL, "Unable to collect gethostbyname()", "ERROR", MB_OK);
WSACleanup();
return 1;
}
/// Creating a socket
SOCKET clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(clientSock == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to create socket", "ERROR", MB_OK);
WSACleanup();
return 1;
}
SOCKADDR_IN serverInfo;
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEnt->h_addr_list);
serverInfo.sin_port = htons(1111);
retVal=connect(clientSock,(LPSOCKADDR)&serverInfo, sizeof(serverInfo));
if(retVal==SOCKET_ERROR)
{
MessageBox(NULL, "Unable to connect()", "ERROR", MB_OK);
WSACleanup();
return 1;
}
MessageBox(NULL, "Connection made sucessfully", "SUCCESS", MB_OK);
char *pBuf = "Request";
MessageBox(NULL, "Sending request from client", "SENDING....", MB_OK);
retVal = send(clientSock, pBuf, strlen(pBuf), 0);
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to send()", "ERROR", MB_OK);
WSACleanup();
return 1;
}
char szResponse[9];
retVal = recv(clientSock, szResponse, 9, 0);
if(retVal == SOCKET_ERROR)
{
MessageBox(NULL, "Unable to recv()", "SOCKET ERROR", MB_OK);
WSACleanup();
return 1;
}
MessageBox(NULL, szResponse, "Got the response from server", MB_OK);
closesocket(clientSock);
WSACleanup();
return 0;
}

