[C] Listening Winsock Server

Level 6
Joined
Nov 1, 2007
Messages
42
Ps. I'm glad you asked me to add an explanation, because i noticed and fixed 3 errors, this was source from a long time ago when i first started using winsock :D

Well, i just put this up on my blog so i thought I'd post it here as well for anyone who's interested in winsock.

Code:
/* Basic Winsock Application By GoSu.SpeeD */

#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <windows.h>

#define PORT 31337

int main()
{
    int sock;
    int sock2;
    int sockaddr_length;
    struct sockaddr_in ZServer;
    struct sockaddr_in ZClient;
    char data[1024];
    int len;
    int loopcounter = 1;
    WSADATA wsaData;
	
    sockaddr_length = sizeof(struct sockaddr_in);

    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) 
    {
        fprintf(stderr, "WSAStartup failure");
        exit(1);
    }
	
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        fprintf(stderr, "Socket Error");
        exit(1);
    }
		
    ZServer.sin_family = AF_INET;
    ZServer.sin_port = htons(PORT);
    ZServer.sin_addr.s_addr = INADDR_ANY;
			
    if ((bind(sock, (struct sockaddr *)&ZServer, sockaddr_length)) == -1)
    {
	fprintf(stderr, "Bind Error");
        exit(1);
    }
	
    if ((listen(sock, 2)) == -1)
    {
        fprintf(stderr, "Error while listening");
	exit(1);
    }
	
    while(1 == loopcounter)
    {
        sleep(10);     
        if ((sock2 = accept(sock, (structsockaddr*)&ZClient,&sockaddr_length)) == -1)
	{
	    fprintf(stderr, "Accepting Error");
	    exit(-1);
	}
		
	while(len)
	{
            len = recv(sock2, data, 1024, 0);
		    
	    if(len)
	    {
	        send(sock2, data, len, 0);
		data[len] = '\0';
		printf("%s", data);
	    }
			 
	}
	printf("\n\nClosing Socket");
	closesocket(sock2);
    }
    closesocket(sock);		
    WSACleanup();
}

/* program will listen on port 31337 when executed
   Code a client to connect to specified port
   OR use telnet to connect, all characters typed
   are streamed to this server program in the console */

/* Compile with gcc: gcc winsock.c -o winsock.exe -lws2_32

Just after main, is the declaration of all our variables.

Code:
sockaddr_length = sizeof(struct sockaddr_in);

stores the size of the struct, in the struct type variable named sockaddr_in, we need this for a parameter for use in later functions such as "bind" and "accept"

Code:
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) 
{
    fprintf(stderr, "WSAStartup failure");
    exit(1);
}

WSAStartup basically allows us to have access to the winsock dll, MAKEWORD(1, 1) just means that the winsock version that we are using is 1.1 and the pointer (pointers point to an address in the memory (e.g 0051104F)) instead of a value like "2") to the WSADATA basically points to the earlier declared variable "wsaData", this is used to receive details of the winsock implementation. by the if statement as a whole, we mean "If WSAStartup does not succeed", when this happens, we use fprintf to print to the ERROR output stream.

Code:
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
    fprintf(stderr, "Socket Error");
    exit(1);
}

here, we are creating a socket named "sock", AF_INET and SOCK_STREAM are just normal ways to create a STREAMING socket, and with the if statement as a whole, we basically say, "If Creation of socket failed", then once again print "socket error" to stderr.

Code:
ZServer.sin_family = AF_INET;
ZServer.sin_port = htons(PORT);
ZServer.sin_addr.s_addr = INADDR_ANY;

here we create the socket family, we chose AF_INET as the family type because it is the most common type for storing IP's and TCP ports. we then use htons to convert the number defined as port in the top define (beside the includes) which is 31337 in this case. Lastly INADDR_ANY as the sin_addr.s_addr part just means that we will start the server on our computer.

Code:
    if ((bind(sock, (struct sockaddr *)&ZServer, sockaddr_length)) == -1)
    {
	fprintf(stderr, "Bind Error");
        exit(1);
    }
	
    if ((listen(sock, 2)) == -1)
    {
        fprintf(stderr, "Error while listening");
	exit(1);
    }

After reading the explanations from the first couple of winsock functions, you should probably be getting the format for this about now. Bind, binds the server to the specified port, and listen, Listens on that specified port for an incoming connection, once again, if the binding or listening fail to happen, we print to stderr (This is an important thing to do, this will help you when looking for bugs)

Code:
while(1 == loopcounter)
    {
        sleep(10);     
        if ((sock2 = accept(sock, (structsockaddr*)&ZClient,&sockaddr_length)) == -1)
	{
	    fprintf(stderr, "Accepting Error");
	    exit(-1);
	}

We start off with an infinite loop because loopcounter is earlier assigned the value of 1 (i do this to avoid CPU usage, a while(1) loop with a sleep function would be sufficient too) we then accept any incoming connect, filling out all the details we have provided/collected on the way to this part, is accepting somehow fails, guess what? we print to stderr (make it a habit :smile:)

Code:
while(len)
	{
            len = recv(sock2, data, 1024, 0);
		    
	    if(len)
	    {
	        send(sock2, data, len, 0);
		data[len] = '\0';
		printf("%s", data);
	    }
			 
	}

we start our while loop which will loop forever because while(variablename) basically means while(variablename is true), so we have an infinite loop, we then call recv, which will receive all our data from our socket "sock2", "data" will store all information recieved, 1024 is the maximum buffer size and we can leave the last parameter as 0 or NULL. the return value of recv is then stored in "len" (the return value in this case is the length of bytes)

We then started our if statement that is always true, and we send the received data to our socket named "sock2", data[len] = '\0' will basically add '\0' to after what was typed in the input, as we know (or should know :smile:) '\0' is the null terminating character which we usually have to leave a space for at the end of arrays etc. Finally we print whatever was received to the console.

Code:
printf("\n\nClosing Socket");
	 closesocket(sock2);
    }
    closesocket(sock);		
    WSACleanup();
}

Lastly, we close our sockets with "closesocket()" and then finally we basically tell the winsock dll that we're finished with it for now, so we call "WSACleanup();

I hope that was a detailed enough explanation, i'm going to go to bed now, i've been up all night finishing a programming project and desperately need some sleep, cya :)
 
Last edited:
Top