I don’t know whether title of the article make sense or not but I will still go with the same. The reason why I write this article. I was learning how to use sockets under windows, I could not find any place that had a tutorial which included every thing i was looking for. After doing my research I put together my knowledge which I gain about socket with this tutorial. I called my article as multithreaded client/server communication the reason is “every time the client connects to server, server created a new thread to serve that client”. This is what multithreaded in the context of my article. I am sure it is clear and informative so the other people can benefit from it.
This article is divided into 2 section:
Server - Create a server socket that listen for a client to connect (multithreaded)
Client - Create a client socket that connect to server socket, to exchange the data .
Using the code
Create the server socket :
WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
This function must be the first Windows Sockets function called by an application or DLL. It allows an application or DLL to specify the version of Windows Sockets API required and to retrieve details of the specific Windows Sockets implementation. The application or DLL may only issue further Windows Sockets API functions after a successful WSAStartup invocation.< /p>
socket(int af, int type, int protocol)
This method creates the socket
bind(SOCKET s, const struct sockaddr FAR * name, int namelen)
Associates a local address with a socket This routine is used on an unconnected datagram or stream socket, before subsequent connects or listens. When a socket is created with socket, it exists in a name space (address family), but it has no name assigned. bind establishes the local association (host address/port number) of the socket by assigning a local name to an unnamed socket. In the Internet address family, a name consists of several components.
listen(SOCKET s, int backlog )
Establishes a socket to listen to a incoming connection To accept connections, a socket is first created with socket, a backlog for incoming connections is specified with listen, and then the connections are accepted with accept. listen applies only to sockets that support connections. This function is typically used by servers that could have more than one connection request at a time: if a connection request arrives with the queue full, the client will receive an error with an indication of WSAECONNREFUSED. It will accept connections until the queue is emptied. If descriptors become available, a later call to listen or accept will re-fill the queue to the current or most recent "backlog'', if possible, and resume listening for incoming connections.
accept(SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen)
This routine extracts the first connection on the queue of pending connections on s, creates a new socket with the same properties as s and returns a handle to the new socket. If no pending connections are present on the queue, and the socket is not marked as non- blocking, accept blocks the caller until a connection is present. If the socket is marked non-blocking and no pending connections are present on the queue, accept returns an error as described below. The accepted socket may not be used to accept more connections. The original socket remains open. The argument addr is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer. The exact format of the addr parameter is determined by the address family in which the communication is occurring. The addrlen is a value-result parameter; it should initially contain the amount of space pointed to by addr; on return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types such as SOCK_STREAM. If addr and/or addrlen are equal to NULL, then no information about the remote address of the accepted socket is returned.
closes a socket
Ends the use of the Windows Sockets DLL.
Most of the functions that have been used for the client to connect to the server are the same as the server with the exception of a few. I will just go through the different functions that have been used for the client.
gethostbyname(const char* FAR name)
gethostbyname returns a pointer to a hostent structure as described under gethostbyaddr. The contents of this structure correspond to the hostname name. A gethostbyname implementation must not resolve IP address strings passed to it. Such a request should be treated exactly as if an unknown host name were passed.
Send / Receive:
Up to this point we have managed to connect with our client to the server. Clearly this is not going to be enough in a real-life application. In this section we are going to look into more details how to use the send/recv functions in order to get some communication going between the two applications. This is not difficult because most of the hard work has been done setting up the server and the client app. before going into the code we are going to look into more details the two functions.
send(SOCKET s, const char FAR * buf, int len, int flags)
send is used on connected datagram or stream sockets and is used to write outgoing data on a socket. For datagram sockets, care must be taken not to exceed the maximum IP packet size of the underlying subnets, which is given by the iMaxUdpDg element in the WSAData structure returned by WSAStartup. If the data is too long to pass atomically through the underlying protocol the error WSAEMSGSIZE is returned, and no data is transmitted.
recv(SOCKET s, const char FAR * buf, int len, int flags)
For sockets of type SOCK_STREAM, as much information as is currently available up to the size of the buffer supplied is returned. If the socket has been configured for in- line reception of out-of-band data (socket option SO_OOBINLINE) and out-of-band data is unread, only out-of-band data will be returned.
How To Run:
1. Download the Client.zip and Server.zip
2. Change the machine name in Client code to the desire machine on which your Server.exe will be running.
3. You should rebuild the code. (both Server and Client)
4. Run the Server.exe on desire server machine.
5. Run Client.exe from local machine, and press Communicate from File menu to start comminication with server. You can run as many Client.exe as possible, server will created a new thread for every new Client.exe.
6. That's all Client/Server communication start.
Points of Interest
This article demostrates how to serve a client by creating new thread !
While working on this article so many people help me, one of the person is my best friend "Sandeep Darekar". Who help me a lot while working on sockets. Last but not least thnax to other engineers also who help me in direct/indirect ways !
I hope this tutorial has been of some use, even if the code implementation is simple it might be of help to develop programs that need to implement the socket API.