Archive for C++
Simple Client in C++
Posted by: | CommentsAlthough a TCP client is fundamentally different from a TCP server, setting up the socket is very much the same. For a server, we called these methods in this order:
socket()→bind()→listen()→accept(), followed by sequences of read() and write().
For a client we will call these methods in this order:
socket()→connect(), followed by sequences of write() and read() depending on what your server does.
To illustrate, I will create a simple HTTP client in C++, which has the following usage:
client www.googolflex.com
It will then make a connection on port 80 of the server specified at the command line, send an HTTP 1.1 request, and then dump the response to the console.
It uses the following variables:
int sock; struct sockaddr_in client; int PORT = 80;
The first thing to do is initialize the socket structure, for this we need the IP address of the host. You can use the gethostbyname(char *) function to do that, which passes back a hostent structure. I have encapsulated the socket setup into a method, which shows how to extract the necessary values from the hostent struct, here:
void setupSocket(char* hostname) {
struct hostent * host = gethostbyname(hostname);
if ( (host == NULL) || (host->h_addr == NULL) ) {
cout << "Error retrieving DNS information." << endl;
exit(1);
}
bzero(&client, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons( PORT );
memcpy(&client.sin_addr, host->h_addr, host->h_length);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
cout << "Error creating socket." << endl;
exit(1);
}
}
If this method executes correctly, then we have a socket, and an address structure that we can use to call connect() with. Here is my encapsulating method:
void connectToHost(char* hostname) {
if ( connect(sock, (struct sockaddr *)&client, sizeof(client)) < 0 ) {
close(sock);
cout << "Could not connect to " << hostname << endl;
exit(1);
}
}
Finally, we can call send()/write() and read()/recv(). This is where your protocol would be implemented, if you were to modify this for use with something other than simple HTTP requests. Here my sendRequest() and getResponse() methods:
void sendRequest(char* hostname) {
string request = "GET / HTTP/1.1\r\nHost: ";
request+= string(hostname);
request += "\r\n\r\n";
if (send(sock, request.c_str(), request.length(), 0) != (int)request.length()) {
cout << "Error sending request." << endl;
exit(1);
}
}
void getResponse() {
char cur;
while ( read(sock, &cur, 1) > 0 ) {
cout << cur;
}
}
In main() I call these four methods in sequence, passing in the hostname parameter where needed. And that’s it. The full source is included at the end of the post.
Socket connections really aren’t that difficult once you’ve done it several times. Next I will be demonstrating how to set up a simple client in Flex using a client. Many scripting languages have abstracted away much of the difficulty surrounding socket connections (as we will see with Flex) leaving you to focus on implementing your protocol.
Download the source for simpleclient here. It can be compiled as follows:
g++ -Wall -o client simpleclient.cpp
Single Threaded Server in C++
Posted by: | CommentsThe versatility of the client-server architecture has always fascinated me. You can write a server once, and plug in whatever protocol you happen to be implementing. The same goes for clients.
I’m going to present here a simple server I implemented in C++. I guess if I had to give a name to the protocol I implemented, I would call it the “Echo Protocol”. There’s only one part of the code I’m going to comment on specifically in this article, and that is the process() method.
There are ample sources on the web and otherwise explaining the use of the socket, bind, listen, and accept methods – which are the basis for socket communication in C and C++.
One book I would recommend for someone serious about network programming (though it hardly needs my recommendation) is UNIX Network Programming, Third Edition by W. Richard Stevens, Bill Fenner and Andrew Rudoff. If you do read this book, be aware that they use wrapper functions throughout the book (i.e. Bind(), Listen()) to add a measure of error checking (see section 1.4 for their explanation). The wrapper functions have the same signature as the corresponding BSD functions, just make them lowercase.
Here is the code for my process() method:
void process() {
// Read the request
//------------------
string request = "";
while(! isRequestDone(request) ) {
// Read from the client
//-----------------------------
char buf;
bzero(&buf, 1);
nread = recv(client_fd, &buf, 1, 0);
request += buf;
if (nread < 0) {
if (errno == EINTR)
continue;// Continue reading
else
break; // No more
}
else if (nread == 0) {
break; // Nothing left to read
}
}
// Do something with the request
//------------------------------
// Send the response:
//------------------------------
string response = request;
int num_b = response.length();
for (int i = 0; i < num_b; i++) {
char cur = response[i];
send(client_fd, &cur, 1, 0);
}
// Close the connection here
close(client_fd);
}
This method is where you would implement the protocol (be it HTTP, or what have you). A crucial step in any interesting protocol would be parsing out the request (something you might do where I have the comment “Do something with the request”) and using that information to construct the response. Sometimes the request parsing is handled while the request is being received. I wanted to keep this example simple (so you’ll also notice I’m receiving and sending only 1 byte at a time… which involves a lot of overhead and I wouldn’t recommend for high load servers sending and receiving larger messages). You could increase the number being read at a time by increasing the size of buf and/or cur.
You can download the complete code for this server here: C++ single threaded server
You can compile this code on Linux with the following command:
g++ -Wall -o bin/server single_threaded_server.cpp
Linux and Windows both use BSD sockets, but I haven’t tried compiling this code on Windows without using g++ on cygwin. You’re on your own there.
This post is part of a series, next I’m going to post a simple C++ client. Then I’m going to present a threaded server architecture, and finally I’m going to post a Flex chat client and implement a simple chat protocol. Stay tuned.

