Servidor escrito en C

Servidor sencillo en C, creacion de un protocolo

Publicado por AlbertoBSD el 2020-07-04 02:58:46

El código mostrado a continuación esta hecho para windows, no es el codigo mas optimo posible y en mi caso abusó mucho de los apuntadores sin embargo es posible adaptarlo para realizar cualquier operación


#include<winsock2.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>

#pragma comment(lib,"ws2_32")

#define BACKLOG 256
struct sockaddr_in *server_sa;

char *readLine(SOCKET descriptor,int *len);
void writeLine(SOCKET descriptor,char *str);
DWORD WINAPI  procesar_peticion(LPVOID descriptor);

int main()	{
	SOCKET s,c;
	SOCKET *toThread;
	WSADATA wsaData;
	DWORD dwThreadId;
	HANDLE hThread;
	int b = 0,iResult;
	char caracter;
	memset(&wsaData,0,sizeof(WSADATA));
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}
	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket");
		return 2;
	}
	server_sa = calloc(1,sizeof(struct sockaddr_in));
	server_sa->sin_family = AF_INET;
	server_sa->sin_port   = htons(10000);
	server_sa->sin_addr.s_addr = htonl(INADDR_ANY);	
	if (bind(s,(struct sockaddr *) server_sa, sizeof(struct sockaddr)) < 0) {
		perror("bind");
		exit(3);
	}
	b = sizeof(struct sockaddr);
	if(listen(s, BACKLOG) ==SOCKET_ERROR)	{
		fprintf(stderr,"listen %s",WSAGetLastError());
		exit(4);
	}
	while(1)	{
		if((c = accept(s,(struct sockaddr *)server_sa, &b)) < 0) {
			printf("WS error code: %i\n",WSAGetLastError());
			perror("accept");
			exit(5);
		}
		toThread = malloc(sizeof(SOCKET));
		memcpy(toThread,&c,sizeof(SOCKET));
		hThread = CreateThread(NULL,0,procesar_peticion,toThread,0,&dwThreadId);
	}
}

DWORD WINAPI  procesar_peticion(LPVOID descriptor)	{
	HANDLE thread_id;
	SOCKET client;
	int read_len;
	int i = 0,j =0;
	int entrar = 1;
	char *linea;
	thread_id = GetCurrentThread();
	memcpy(&client,descriptor,sizeof(SOCKET));
	free(descriptor);
	do	{
		linea = readLine(client,&read_len);
		if(read_len == -1)	{
			entrar = 0;
		}
		else	{
			printf("Linea leida: %s\nBytes leidos %i\n",linea,read_len);

			writeLine(client,linea);
		}
		/*
		i++;
		if(i == 5)	{
			entrar = 0;
		}
		*/
		/*
		if(strncmp("exit",linea,4) == 0)	{
			entrar = 0;
		}
		*/
		/*
		if(read_len == 10)	{
			entrar = 0;
		}
		*/
		free(linea);
	}while(entrar == 1);
	closesocket(client);
	CloseHandle(thread_id);	
}

char *readLine(SOCKET descriptor,int *len)	{
	char *buffer = NULL;
	int i = 0,entrar = 1,len_read,max;
	buffer = malloc(64);
	max = 64;
	do	{
		if(i == max)	{
			max *= 2;
			buffer = realloc(buffer,max);
			if( buffer == NULL )	{
				fprintf(stderr,"realloc(): buffer len %i\n",i);
				exit(0);
			}
		}
		len_read = recv(descriptor,buffer + i,1,0);
		if(len_read == 1)	{
			switch(buffer[i])	{
				case 0xD:
				case 0xA:
					buffer[i] = '\0';
					entrar = 0;
				break;
				default:
					i++;
				break;
			}
		}
		else	{
			buffer[i] = '\0';
			entrar = 0;
			if(i == 0)	{
				i = -1;
			}
		}
	}while(entrar && i < 1000);
	if( len != NULL )	{
		*len = i;
	}
	return buffer;
}

void writeLine(SOCKET descriptor,char *str)	{
	int len;
	len = strlen(str);
	//send(descriptor,"Usted escribio: ",16,0);
	send(descriptor,str,len,0);
	//send(descriptor,"\n",1,0);
}
<p>Compilamos el siguiente el código con el siguiente comando</p>
<custom_code>gcc -o servidor_eco.exe servidor_eco.c -lws2_32

Ejecutamos el servidor

servidor_eco.exe

Nos conectamos al servidor utilizando el cliente netcat:

ncat localhost 10000

Y comenzamos a mandar datos desde el cliente, terminaremos aproximadamente con la salida mostrada a continuación:


Saludos!