//////////////////////////////////////////////////////char*message; message ="GET / HTTP/1.1\r\n\r\n";if( send(s , message ,strlen(message) ,0) <0) {puts("Send failed");return1; } puts("Data Send\n"); //////////////////////////////////////////////////////char server_reply[2000];int recv_size;//Receive a reply from the serverif((recv_size =recv(s , server_reply ,2000,0)) == SOCKET_ERROR) {puts("recv failed"); } puts("Reply received\n");//Add a NULL terminating character to make it a proper string before printing server_reply[recv_size] ='\0';puts(server_reply);
Close Socket
Use closesocket() and WSACleanup to unload the library
closesocket(s);WSACleanup();
Example code for Client
/* Example code for Client TCP socket*/#include<stdio.h>#include<winsock2.h>#include<ws2tcpip.h>#pragmacomment(lib,"ws2_32.lib") //Winsock Libraryintmain(int argc,char* argv[]){ WSADATA wsa; SOCKET s;struct sockaddr_in server;char* message, server_reply[2000];int recv_size =2000; ////////////////////////////////////////////////////////// Initializeprintf("\nInitialising Winsock...");if (WSAStartup(MAKEWORD(2,2),&wsa)!=0) {printf("Failed. Error Code : %d", WSAGetLastError());return1; }printf("Initialised.\n"); //////////////////////////////////////////////////////// //Create a socketif ((s =socket(AF_INET, SOCK_STREAM,0)) == INVALID_SOCKET) {printf("Could not create socket : %d", WSAGetLastError()); }printf("Socket created.\n"); ////////////////////////////////////////////////////////// Connect to server - google.com//server.sin_addr.s_addr = inet_addr("74.125.235.20");//server.sin_family = AF_INET;//server.sin_port = htons(80);// Connect to server - local host//server.sin_addr.s_addr = inet_addr("192.168.0.28");inet_pton(AF_INET,"192.168.0.28",&(server.sin_addr.s_addr));server.sin_family = AF_INET;server.sin_port =htons(8888);//Connect to remote serverif (connect(s, (struct sockaddr*)&server,sizeof(server))<0) {puts("connect error");return1; }puts("Connected"); //////////////////////////////////////////////////////// //Send some data message = (char*)"GET / HTTP/1.1\r\n\r\n";if (send(s, message, strlen(message),0)<0) {puts("Send failed");return1; }puts("Data Send\n"); //////////////////////////////////////////////////////////Receive a reply from the serverif ((recv_size =recv(s, server_reply,2000,0)) == SOCKET_ERROR) {puts("recv failed"); }puts("Reply received\n");//Add a NULL terminating character to make it a proper string before printing server_reply[recv_size] ='\0';puts(server_reply); ////////////////////////////////////////////////////////// Close socketclosesocket(s);WSACleanup(); ////////////////////////////////////////////////////////return0;}
Server
Open a socket (see client)
Bind to address and port.
Listen for incoming connections.
Accept connections
Read/Send
Bind
We bind a socket to a particular IP address and a certain port number. We ensure that all incoming data which is directed towards this port number is received by this application
we need to do is listen for connections. For this we need to put the socket in listening mode. Function listen is used to put the socket in listening mode
//Listen
listen(s , 3);
Accept connection
// Some code
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s , (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
}
puts("Connection accepted");
Sending Receiving data
Replying to the client
We had to use a getchar because otherwise the output would scroll out of the client terminal without waiting
// Some code//Reply to client message ="Hello Client , I have received your connection. But I have to go now, bye\n";send(new_socket , message ,strlen(message) ,0);getchar();
Example code for Live Server
/* Live Server on port 8888*/#include<io.h>#include<stdio.h>#include<winsock2.h>#pragmacomment(lib,"ws2_32.lib") //Winsock Libraryintmain(int argc ,char*argv[]){ WSADATA wsa; SOCKET s , new_socket;struct sockaddr_in server , client;int c;char*message;printf("\nInitialising Winsock...");if (WSAStartup(MAKEWORD(2,2),&wsa)!=0) {printf("Failed. Error Code : %d",WSAGetLastError());return1; }printf("Initialised.\n");//Create a socketif((s =socket(AF_INET , SOCK_STREAM ,0 )) == INVALID_SOCKET) {printf("Could not create socket : %d", WSAGetLastError()); }printf("Socket created.\n");//Prepare the sockaddr_in structureserver.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port =htons( 8888 );//Bindif( bind(s ,(struct sockaddr *)&server ,sizeof(server))== SOCKET_ERROR) {printf("Bind failed with error code : %d", WSAGetLastError());exit(EXIT_FAILURE); }puts("Bind done");//Listen to incoming connectionslisten(s ,3);//Accept and incoming connectionputs("Waiting for incoming connections..."); c =sizeof(struct sockaddr_in);while( (new_socket =accept(s , (struct sockaddr *)&client,&c)) != INVALID_SOCKET ) {puts("Connection accepted");//Reply to the client message = (char*)"Hello Client , I have received your connection. But I have to go now, bye\n";send(new_socket , message , strlen(message) ,0); }if (new_socket == INVALID_SOCKET) {printf("accept failed with error code : %d", WSAGetLastError());return1; }closesocket(s);WSACleanup();return0;}
Trouble Shooting:
inet_addr'' use inet_pton() or InetPton()~ : 여기 클릭
So now the server is running nonstop and the telnet terminals are also connected nonstop. Now close the server program.
All telnet terminals would show "Connection to host lost."
Good so far. But still there is not effective communication between the server and the client.
The server program accepts connections in a loop and just send them a reply, after that it does nothing with them. Also it is not able to handle more than 1 connection at a time. So now its time to handle the connections , and handle multiple connections together.
Handle multiple connections
To handle every connection we need a separate handling code to run along with the main server accepting connections.
One way to achieve this is using threads. The main server program accepts a connection and creates a new thread to handle communication for the connection, and then the server goes back to accept more connections.
On Linux threading can be done with the pthread (posix threads) library. It would be good to read some small tutorial about it if you dont know anything about it. However the usage is not very complicated.
We shall now use threads to create handlers for each connection the server accepts.
Linux
#include<stdio.h>#include<string.h>//strlen#include<stdlib.h>//strlen#include<sys/socket.h>#include<arpa/inet.h>//inet_addr#include<unistd.h>//write#include<pthread.h>//for threading , link with lpthreadvoid*connection_handler(void*);intmain(int argc ,char*argv[]){int socket_desc , new_socket , c ,*new_sock;struct sockaddr_in server , client;char*message;//Create socket socket_desc =socket(AF_INET , SOCK_STREAM ,0);if (socket_desc ==-1) {printf("Could not create socket"); }//Prepare the sockaddr_in structureserver.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port =htons( 8888 );//Bindif( bind(socket_desc,(struct sockaddr *)&server ,sizeof(server))<0) {puts("bind failed");return1; }puts("bind done");//Listenlisten(socket_desc ,3);//Accept and incoming connectionputs("Waiting for incoming connections..."); c =sizeof(struct sockaddr_in);while( (new_socket =accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ) {puts("Connection accepted");//Reply to the client message ="Hello Client , I have received your connection. And now I will assign a handler for you\n";write(new_socket , message , strlen(message));pthread_t sniffer_thread; new_sock =malloc(1);*new_sock = new_socket;if( pthread_create( &sniffer_thread ,NULL, connection_handler , (void*) new_sock)<0) {perror("could not create thread");return1; }//Now join the thread , so that we dont terminate before the thread//pthread_join( sniffer_thread , NULL);puts("Handler assigned"); }if (new_socket<0) {perror("accept failed");return1; }return0;}/* * This will handle connection for each client * */void*connection_handler(void*socket_desc){//Get the socket descriptorint sock =*(int*)socket_desc;int read_size;char*message , client_message[2000];//Send some messages to the client message ="Greetings! I am your connection handler\n";write(sock , message , strlen(message)); message ="Now type something and i shall repeat what you type \n";write(sock , message , strlen(message));//Receive a message from clientwhile( (read_size =recv(sock , client_message ,2000,0)) >0 ) {//Send the message back to clientwrite(sock , client_message , strlen(client_message)); }if(read_size ==0) {puts("Client disconnected");fflush(stdout); }elseif(read_size ==-1) {perror("recv failed"); }//Free the socket pointerfree(socket_desc);return0;}
This one looks good , but the communication handler is also quite dumb. After the greeting it terminates. It should stay alive and keep communicating with the client.
One way to do this is by making the connection handler wait for some message from a client as long as the client is connected. If the client disconnects , the connection handler ends.
So the connection handler can be rewritten like this
The above connection handler takes some input from the client and replies back with the same. Simple! Here is how the telnet output might look
$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello Client , I have received your connection. And now I will assign a handler for you
Greetings! I am your connection handler
Now type something and i shall repeat what you type
Hello
Hello
How are you
How are you
I am fine
I am fine
So now we have a server thats communicative. Thats useful now.
Linking the pthread library
When compiling programs that use the pthread library you need to link the library. This is done like this :