Create client-server model c / c ++ with two clients

0

I need to create a connection between 2 clients and 1 server using sockets in the linux and c ++ operating system. The problem I am facing is that I can not sync the messages and the server always ends up crashing at some point. I am new to networks and therefore I would like to know how best to implement this type of connection. Here is the code for the server:

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

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 8080
#define BUFFER_LENGTH 4096

int main()
{
    struct sockaddr_in client, client2, server;
    int serverfd, clientfd, clientfd2;

    char buffer_server[BUFFER_LENGTH];

    printf("Comecando servidor\n");

    //Criando socket IPV4, protocolo TCP
    serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if(serverfd == -1) {
        perror("Nao foi possivel criar socket");
        return EXIT_FAILURE;
    }
    printf("Socket de servidor criado: %d\n", serverfd);

    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    memset(server.sin_zero, 0x0, 8);

    //Configurando socket
    int yes = 1;
    if(setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR,
                  &yes, sizeof(int)) == -1) {
        perror("Socket options error:");
        return EXIT_FAILURE;
    }

    //Associando socket à porta
    if(bind(serverfd, (struct sockaddr*)&server, sizeof(server)) == -1 ) {
        perror("Erro de associar socket a porta");
        return EXIT_FAILURE;
    }

    //Começando a escutar clientes
    if(listen(serverfd, 2) == -1) {
        perror("Erro de escuta");
        return EXIT_FAILURE;
    }

    printf( "Escutando cliente na porta %d\n", PORT);

    socklen_t client_len = sizeof(client);
    if ((clientfd=accept(serverfd,
        (struct sockaddr *) &client, &client_len )) == -1) {
        perror("Erro ao aceitar cliente");
        return EXIT_FAILURE;
    }

    socklen_t client_len2 = sizeof(client2);
    if ((clientfd2=accept(serverfd,
        (struct sockaddr *) &client2, &client_len2 )) == -1) {
        perror("Erro ao aceitar cliente");
        return EXIT_FAILURE;
    }

    memset(buffer_server, 0x0, BUFFER_LENGTH);
    int room1 = 1;
    int room2 = 1;
    

    int message_len;

    while(1){
    	memset(buffer_server, 0x0, BUFFER_LENGTH);
   		message_len = recv(clientfd, buffer_server, BUFFER_LENGTH, 0);
   		send(clientfd, "ok", strlen("ok"), 0);
    	if(strcmp(buffer_server, "getroom2") == 0 ){
    		printf("%s - %s \n", "Chegou", buffer_server);
    		memset(buffer_server, 0x0, BUFFER_LENGTH);
    		recv(clientfd, buffer_server, BUFFER_LENGTH, 0);
    		printf("%s\n", buffer_server);
    		room1 = atoi(buffer_server);
    		if(room1 == 2 && room2 == 2){
       	 		strcpy(buffer_server, "setroom2");
       	 		printf("%s\n", buffer_server);
        		send(clientfd, buffer_server, strlen(buffer_server), 0);
    		}else{
    			printf("%s\n", buffer_server);
    			strcpy(buffer_server, "NOPS");
        		send(clientfd, buffer_server, strlen(buffer_server), 0);
    		}
        
    	}
    	memset(buffer_server, 0x0, BUFFER_LENGTH);
   		recv(clientfd2, buffer_server, BUFFER_LENGTH, 0);
   		send(clientfd, "ok", strlen("ok"), 0);
   		printf("%s\n", buffer_server);

    	if(strcmp(buffer_server, "getroom2") == 0 ){
    		recv(clientfd2, buffer_server, BUFFER_LENGTH, 0);
    		printf("%s\n", buffer_server);
    		room2 = atoi(buffer_server);
    		if(room1 == 2 && room2 == 2){
       	 		strcpy(buffer_server, "setroom2");
        		send(clientfd2, buffer_server, strlen(buffer_server), 0);
    		}else{
    			strcpy(buffer_server, "NOPS");
        		send(clientfd2, buffer_server, strlen(buffer_server), 0);
    		}
    	}
    }  
}
    
asked by anonymous 08.11.2018 / 00:21

1 answer

0

Even though I do not use "non-blocking" mode as I suggested in the comment your program has errors.

A very visible error is the lack of error handling in function calls.

Example when doing recv:

message_len = recv(clientfd, buffer_server, BUFFER_LENGTH-1, 0);
if (message_len == -1)
{
  int err = errno;
  printf("erro %d na recepcao do cliente 1\n");
  exit(1);
}
if (message_len == 0)
{
  printf("client 1 fechou conexao\n");
  exit(1);
}

Example when doing a send:

result = send(clientfd, "ok", 2, 0);
if (result == -1)
{
  int err = errno;
  printf("erro %d no envio ao cliente 1\n", err);
  exit(1);
}
if (result != 2)
{
  printf("implementar tratamento de send incompleto no cliente 1\n");
  exit(1);
}

There is also the problem that the code is not robust in certain parts
For example, check the command "getroom2":

if (strcmp(buffer_server, "getroom2") == 0)
{
  // ...
}

It would be advisable to check if the size received matches the size of the command, like this:

// ...
static const char cmd_getroom2[] = "getroom2";
const int size_cmd_getroom2 = sizeof(cmd_get_room2)) - 1;
// ...
if (message_len == size_cmd_getroom2 && memcmp(buffer_server, cmd_getroom2, size_cmd_getroom2))
{
  // ok, recebeu comando getroom2
  // ...
}
else
{
  // verificar o que aconteceu
  // etc
}

Finally, implement the error handling part as I showed above. While the error handling is not being done you will not be able to behave consistently in your program.

    
10.11.2018 / 18:56