0

I am having trouble figuring out how to store client handles without blocking the server. I am following the concurrent server model detailed in "The Socket Networking API" by Stevens.

My program creates tic tac toe matches between players.

The structure of the program is this: The server handles both TCP/UDP connections. The client program can either query or connect to the server. If the client queries, the UDP socket handles the query by returning a list of the handles of already connected clients.

If the client connects, the TCP socket handles the connection by 1. Asking the client for a handle and 2. Storing their handle. If there are two clients who are connected, a separate process is spawned to create a match between them (but this is not relevant now).

In my program, I am multiplexing the TCP/UDP socket with select(). My current issue is how to deal with asking and storing client handles without blocking.

I have considered:

  1. creating another thread to deal with asking and receiving client handle.
  2. Keeping a list of of connected client sockets and add them to fd_set data structure and multiplex between them in addition to the TCP/UDP sockets.

  3. Spawning another process to deal with asking/receiving handles, but this is not probable since I am storing the handles in a global linked list data structure so that the server can return a list when queried. Communicating back to parent would be too cumbersome.

*The code below has not been tested yet and is incomplete since I have not figured out how to resolve this issue.

    game_head = NULL; game_tail = game_head;

    /* Creating TCP listening socket */
    tcp_listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(TCP_PORT);
    bind(tcp_listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    listen(tcp_listenfd, LISTENQ);

    /* Creating UDP socket */
    udpfd = socket(AF_INET, SOCK_DGRAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(UDP_PORT);
    bind(udpfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    /* Signal handling (also possibly handle SIGCHLD)*/
    signal(SIGINT, sighandler);
    signal(SIGUSR2, sighandler);

    FD_ZERO(&rset);
    maxfdp1 = max(tcp_listenfd, udpfd) + 1;
    while(1) {
            if (terminate)
                    terminate_program();
            FD_SET(tcp_listenfd, &rset);
            FD_SET(udpfd, &rset);
            if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
                    if (errno == EINTR)
                            continue;
                    else
                            perror("select error");
            }

            if (FD_ISSET(tcp_listenfd, &rset)) {
                    len = sizeof(cliaddr);
                    tcp_connfd = accept(tcp_listenfd, (struct sockaddr *) &cliaddr, &len);
                    close(tcp_connfd);
            }

            if (FD_ISSET(udpfd, &rset)) {

            }
    }
mrQWERTY
  • 4,039
  • 13
  • 43
  • 91

1 Answers1

0

Don't close tcp_listenfd. Use an array of TCP connectors i.e. tcp_connfd[10] or something, and then keep count of the amount of TCP's you have. For each client, assign them a new number.

Good luck!

acenturyandabit
  • 1,188
  • 10
  • 24