Socket between 2 clients and 1 server in C

8

How to receive two connections?

The system consists of 2 clients and 1 server, the server must receive the connections and initiate a sequential conversation with the clients. I was able to implement the communication between 1 client and the server (the serial communication via terminal is working), I do not know how to get the second connection with the second client. Because through this solution I can implement the business logic where the server will receive information processing and returns them.

ServicorMain.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <fcntl.h>

#define PORTA 8585
#define BYTE 1024

main(){
        char mensagem[BYTE], *loc;
        int pontarq, tbuf, skt, tskt, escolha;
        struct sockaddr_in serv;

        system("clear");
        /**INICIALIZA ESTRUTURA SOCKETS*/
        skt = socket(AF_INET, SOCK_STREAM, 0);
        serv.sin_family = AF_INET;
        serv.sin_addr.s_addr = INADDR_ANY;
        serv.sin_port = htons (PORTA);
        memset(&(serv.sin_zero),0x00,sizeof(serv.sin_zero));
        tskt = sizeof(struct sockaddr_in);

        printf("\n    ############### Server ###############\n\n");
        /**SOCKET INICIALIZA LISTENER PARA OUVIR PORTA*/
        bind(skt,(struct sockaddr *)&serv,sizeof(struct sockaddr));
        listen(skt,1);
        printf(">> Servidor esta escutando na porta %d\n\n",PORTA);

        /**RECEBE NOVAS CONEXÕES*/
        //O problema acho que está aqui, preciso receber mais uma conexão para o sistema continuar.
        skt = accept(skt,(struct sockaddr *)&serv,&tskt);
        printf(">> A Conexao com o endereco %s foi estabelecida\n\n",inet_ntoa(serv.sin_addr));


        /**ENVIA MENSAGEM PARA CLIENTE*/
        strcpy(mensagem,"Servidor diz: olá!!!");
        send(skt,mensagem,strlen(mensagem), 0);
        sendto()
        send()
        sent
        /**RECEBE MENSAGEM DE CLIENTE*/
        tbuf = recv(skt, mensagem,BYTE, 0);
        mensagem[tbuf]=0x00;
        printf(">: %s\n",mensagem);


        /**LOOP DE COMUNICAÇÃO ENTRE CLIENTE E SERVIDOR*/
        do{
        ///recebe
        tbuf = recv(skt,mensagem,BYTE,0);
        mensagem[tbuf]=0x00;
        printf(">: Cliente diz: %s\n",mensagem);

        ///envia
        printf("> ");
        gets(mensagem);
        send(skt, mensagem, strlen(mensagem), 0);


        }while(strcmp(mensagem,"/x") != 0); ///COMUNICAÇÃO SE ENCERRA QUANDO USUARIO ENVIAR MSG= /X

        close(skt);
        printf(">> A Conexao com o host %s foi encerrada!!!\n\n",inet_ntoa(serv.sin_addr));
        exit(0);
    }

ClientMain.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>


#define SERVER_IP "127.0.0.1"
#define BYTE 1024
#define PORTA 8585
#define TITULO "\n    ############### BeM VinDo ###############\n\n"

void imprimirAguarde(void);

/************************
*          MAIN         *
************************/
main ()
{

    char mensagem[BYTE], *loc;
    int tbuf, skt, escolha;
    struct sockaddr_in serv;
    system("clear");

    /**INICIALIZA ESTRUTURA SOCKETS*/
    skt = socket(AF_INET, SOCK_STREAM, 0);
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = inet_addr(SERVER_IP);
    serv.sin_port = htons (PORTA);
    memset (&(serv.sin_zero), 0x00, sizeof (serv.sin_zero));

    /**INICIA COMUNICAÇÃO COM SERVIDOR*/
    while(connect (skt, (struct sockaddr *)&serv, sizeof (struct sockaddr)) != 0){
        imprimirAguarde();      ///AGUARDA SERVIDOR SE COMUNICAR
    }
    printf(">> A Conexao com o Servidor %s foi estabelecida na porta %d \n\n",SERVER_IP,PORTA);
    printf(">> Envie /x pra sair \n\n");


    /**RECEBE MENSAGEM DO SERVIDOR*/
    tbuf = recv (skt, mensagem, BYTE, 0);
    mensagem[tbuf] = 0x00;
    printf (">: %s\n",mensagem);

    /**ENVIA MENSAGEM PARA O SERVIDOR*/
    strcpy(mensagem, "Cliente diz: olá!!!");
    send(skt, mensagem, strlen(mensagem), 0 );


    /**LOOP DE COMUNICAÇÃO ENTRE CLIENTE E SERVIDOR*/
    do{
        ///envia
        printf("> ");
        gets(mensagem);
        send(skt, mensagem, strlen(mensagem), 0);

        ///recebe
        tbuf = recv (skt, mensagem, BYTE, 0);
        mensagem[tbuf] = 0x00;
        printf (">: Servidor diz: %s\n",mensagem);

    }while(strcmp(mensagem,"/x")!= 0);    ///COMUNICAÇÃO SE ENCERRA QUANDO USUARIO DIGITAR /X


    /**FINALIZA CONEXÃO*/
    close(skt);
    printf (">>A conexao com o servidor foi finalizada!!!\n\n");
    exit(0);
}



/**************************************************************
*   FUNÇÃO RESPOSÁVEL POR IMPRIMIR MENSAGER NA TELA           *
*   ENQUANTO AGUARDA ALGUM SERVIDOR ESTABELECER COMUNICAÇÃO   *
***************************************************************/
void imprimirAguarde(){
    int i=0;
    char dot[12] = "";
    for(i=0; i<4;i++){
        system("clear");
        printf(TITULO);
        printf("\n\nProcurando servidor.");
        printf("\nAguarde %s\n\n", dot);
        strcat(dot,".");
        sleep(1);
    }
    strcpy(dot, "");
}
    
asked by anonymous 03.12.2014 / 16:54

1 answer

4

You basically have three paths:

1) delegate the incoming connection socket in accept () to a child process, using fork (). An example you can rely on is link .

2) Use select () or poll () to handle all sockets, including listening, in a single process. An example is link .

3) use threads, one thread for each connection , keeping the main thread only for the listening socket.

Option (1) is simplest in all respects: it changes your original program a little and ensures that one connection does not interfere with the other (because each one runs in a separate process).

Option (2) is the most elegant from a POSIX programming point of view because it saves resources (uses only one process and one thread). It is also possible to embed timeout handling in the select () or poll () call. On the other hand it is the most complex to implement: your program has to store the state of each connection and react asynchronously to the received data, erase the state when its connection closes, etc.

Option (3) is usually discouraged by the additional complexity. Dealing with threads is always trouble, only used when it is highly justified. It is interesting to note that in languages like Java, using thread would be the only option because you can not instantiate child processes and there is no asynchronous programming in Java.

Note that this answer is intended to answer the original question: how to serve more than one customer at a time. There are many scalability considerations in case your server addresses thousands or tens of thousands of concurrent connections, and the right answer would then depend on how your application protocol really works.

    
09.12.2014 / 19:13