Window Socket Programming
Window: Socket programming with winsock
Requirement
Window OS only
C programming
Link:
ws2_32.lib
Include:
winsock2.h

Reading List
Client
We wil learn how to :
Initialize Winsock
Create a socket
Connect to remote server
Send some data
Receive a reply
Initialising Winsock
Winsock first needs to be initialiased with
int WSAAPI WSAStartup( [in] WORD wVersionRequested, [out] LPWSADATA lpWSAData );
Second one is a WSADATA structure
/*
Initialise Winsock
*/
#include<stdio.h>
#include<winsock2.h>
// It automatically links this library to compiler
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.");
return 0;
}
Creating Socket
The socket()
function is used to create a socket.
SOCKET WSAAPI socket( [in] int af, [in] int type, [in] int protocol );
Address Family : AF_INET (this is IP version 4)
Type : SOCK_STREAM (this means connection oriented TCP protocol)
Protocol : 0 [ or IPPROTO_TCP , IPPROTO_UDP ]
WSADATA wsa;
SOCKET s;
////////////////////////////////////////////////////////
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
Connect to Server
Need (1) IP address (2) Port number to connect
Use sockaddr_in
structure with proper values filled in.
////////////////////////////////////////////////////////
// Connect to server
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("74.125.235.20");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
/////////////////////////////////////////////////
// Defined in <winsock2.h>
/////////////////////////////////////////////////
// IPv4 AF_INET sockets:
struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
typedef struct in_addr {
union {
struct {
u_char s_b1,s_b2,s_b3,s_b4;
} S_un_b;
struct {
u_short s_w1,s_w2;
} S_un_w;
u_long S_addr;
} S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
Function inet_addr
is a very handy function to convert an IP address to a long format.
server.sin_addr.s_addr = inet_addr("74.125.235.20");
``
Sending Data, Receive Data
Use send( )
to send some data
Use recv()
to receive data
//////////////////////////////////////////////////////
char *message;
message = "GET / HTTP/1.1\r\n\r\n";
if( send(s , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
//////////////////////////////////////////////////////
char server_reply[2000];
int recv_size;
//Receive a reply from the server
if((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>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc, char* argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char* message, server_reply[2000];
int recv_size = 2000;
////////////////////////////////////////////////////////
// Initialize
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
////////////////////////////////////////////////////////
//Create a socket
if ((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 server
if (connect(s, (struct sockaddr*)&server, sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
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");
return 1;
}
puts("Data Send\n");
////////////////////////////////////////////////////////
//Receive a reply from the server
if ((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
closesocket(s);
WSACleanup();
////////////////////////////////////////////////////////
return 0;
}
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
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
}
puts("Bind done");
Listen for connection
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>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(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());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( 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 connections
listen(s , 3);
//Accept and incoming connection
puts("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());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
Now run the program in 1 terminal , and open 3 other terminals. From each of the 3 terminal do a telnet to the server port.
Run telnet like this. It will launch the interactive prompt.
C:\>telnet
At the telnet shell, run the command "open localhost 8888". This command will try to connect to localhost on port number 8888.
Welcome to Microsoft Telnet Client
Escape Character is 'CTRL+]'
Microsoft Telnet> open localhost 8888
Next you should see the following message at the telnet prompt. This message is received from the socket server running on port 8888.
Hello Client , I have received your connection. But I have to go now, bye
On the other hand, the server terminal would show the following messages, indicating that a client connected to it.
Initialising Winsock...Initialised.
Socket created.
Bind done
Waiting for incoming connections...
Connection accepted
Connection accepted
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 lpthread
void *connection_handler(void *);
int main(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 structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("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");
return 1;
}
//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");
return 1;
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int 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 client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//Send the message back to client
write(sock , client_message , strlen(client_message));
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
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 :
$ gcc program.c -lpthread
Last updated
Was this helpful?