This is a sequel to the article Beginning Winsock Programming - Simple TCP server
and if you have not read that already I would recommend that you do that first.
In this article I'll show how you can write a simple TCP client program. We'll
write a program that will connect to an HTTP server and retrieve a file.
Program Flow of a simple TCP client
- Initialize WinSock library using
- Create a IPPROTO_TCP SOCKET using
- Retrieve host information using
- Connect to the server using the socket we created, using
- Send and Receive data using
recv() till our tcp chat is over
- Close the socket connection using
- De-Initialize WinSock using
As with every other WinSock program we need to initialize the WinSock
library. Basically it is also a kind of check to see if WinSock is available on
the system in the precise version we expect it to be.
Create the SOCKET
The socket is the entity that acts as the endpoint between the client and the
server. When a client is connected to a server, there are two sockets. The
socket at the client side and the corresponding socket at the server side. Lets
call them CLIENTSOCK and SERVERSOCK. When the client uses
send() on CLIENTSOCK
the server can use
recv() on the SERVERSOCK to receive what the client sends.
Similarly the reverse is also true. For our purposes we create the socket using a
Getting host information
Obviously we need to get info about the host [the server] before we can
connect to it. There are two functions we can use -
gethostbyname() function is used when we have the DNS name
of our server, something like codeproject.com or ftp.myserver.org. The
gethostbyaddr() function is used when we actually have the IP address of the
server to connect to, something like 192.168.1.1 or 18.104.22.168.
Obviously we would want to give our end user the option of entering either a
DNS name or an IP address. Thus for making that part of it transparent to him,
we do a little trick as shown below. We use the function
inet_addr() on the
entered string. The
inet_addr() function converts an IP address into a standard
network address format. Thus if it returns failure, we now know that the string
cannot be an IP address, if it succeeds we assume that it was a valid IP
Connecting to the server
connect() function is used to establish a connection to the destination
server. We pass it the socket we created earlier as well as a
structure. We populate the
sockaddr with the host address returned by
gethostbyaddr(), as well as enter a valid port to connect to.
Once the socket connection is established the client and the server can
recv() data between themselves. This is popularly referred to as TCP
chatting. In our particular case we need to HTTP chat, which is comparatively
simple when you consider other slightly more complicated protocols like SMTP or
POP3. The HTTP GET command is used to retrieve a file from the HTTP server. This
might be an HTML file or an image file or a zip or an MP3 or whatever. It is
send thus [in it's simplest form]. There are other slightly more complex ways of
using this command.
And in our program we do something like this to send the GET command :-
Once we have send the command we know that the server is going to start
sending us the file we just requested. Just as we used
send() to send our
command we can use
recv() to receive the data that the server is going to send
us. We loop on
recv() till it returns zero when we understand that the server
has finished sending us the data. And in our particular case we write all this
data to a file as our intention is to download and save a file.
Close the connection
Now that our chat is over, we must close the connection. In our case the HTTP
connection is closed by the server the moment it finishes sending the file, but
that doesn't matter. We need to close our socket and release the resource. In
more complex chats we usually call
shutdown() before we call
ensure that the buffers are flushed. Otherwise we might encounter some data
WSACleanup() to conclude our usage of WinSock.