开发者

C, socket programming: Connecting multiple clients to server using select()

I'm trying to make a server that can be connected to by multiple clients. Here's my code so far:

Client:

int main(int argc, char **argv) {

  struct sockaddr_in servaddr;
  int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (sock == -1) perror("Socket");

  bzero((void *) &servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(6782);
  servaddr.sin_addr.s_addr = inet_addr(<server_ip_address>);

  if (-1 == connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    perror("Connect");

  while(1) {

    char message[6];
    fgets(message, 6, stdin);

    message[5] = '\0';

    send(sock, message, 6, 0);
  }


  close(sock);
}

Server:

int main(int argc, char **argv) {

  fd_set fds, readfds;
  int i, clientaddrlen;
  int clientsock[2], rc, numsocks = 0, maxsocks = 2;

  int serversock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (serversock == -1) perror("Socket");

  struct sockaddr_in serveraddr, clientaddr;  
  bzero(&serveraddr, sizeof(struct sockaddr_in));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  serveraddr.sin_port = htons(6782);

  if (-1 == bind(serversock, (struct sockaddr *)&serveraddr, 
                 sizeof(struct sockaddr_in))) 
    perror("Bind");

  if (-1 == listen(serversock, SOMAXCONN))
    perror("Listen");

  FD_ZERO(&fds);
  FD_SET(serversock, &fds);

  while(1) {

    readfds = fds;
    rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);

    if (rc == -1) {
      perror("Select");
      break;
    }

    for (i = 0; i < FD_SETSIZE; i++) {
      if (FD_ISSET(i, &readfds)) {
        if (i == serversock) {
          if (numsocks < maxsocks) {
            clientsock[numsocks] = accept(serversock,
                                      (struct sockaddr *) &clientaddr,
                                      (socklen_t *)&clientaddrlen);
            if (clientsock[numsocks] == -1) perror("Accept");
            FD_SET(clientsock[numsocks], &fds);
            numsocks++;
          } else {
            printf("Ran out of socket space.\n");

          }
        } else {
          int messageLength = 5;
          char message[messageLength+1];
          int in, index = 0, limit = messageLength+1;

          while ((in = recv(clientsock[i], &message[index], limit, 0)) > 0) {
            index += in;
            limit -= in;
          }

          printf("%d\n", index);
          printf("%s\n", message);

        }
      }
    }
  }

  close(serversock);
  return 0;
}

As soon as a client connects and sends its first message, the ser开发者_StackOverflow中文版ver just runs in an infinite loop, and spits out garbage from the message array. recv doesn't seem to receive anything. Can anyone see where i go wrong?


Two issues in your code:

  • You should do recv(i, ...) instead of recv(clientsock[i], ...)

  • After that you do not check if recv() failed, and therefore printf() prints out the uninitialised buffer message, hence the garbage in the output


You need to check for limit <= 0 in your read loop, before you call read.


In the while loop for the server, change the code to do recv(i) instead of recv(clientsocks[i]). I have implemented this code and it works with this change.


I replaced the else with the below and it works

 } else {
/*                  int messageLength = 5;
                    char message[messageLength+1];
                    int in, index = 0, limit = messageLength+1;

                    memset ( &message[index] , 0, sizeof ( message [index] ) );

                    while ((in = recv(i, &message[index], limit, 0)) > 0) {
                        index += in;
                        limit -= in;
                    }

                    printf("%d\n", index);
                    printf("%s\n", message);
*/
                    bzero(buf, sizeof(buf));
                    if ((rval = read(i, buf, 1024)) < 0)
                        perror("reading stream message");
                    else if (rval == 0)
                        printf("Ending connection\n");
                    else
                        printf("-->%s\n", buf);

                }


1) It is a good practice to use PF_INET(protocol family) rather than
AF_INET(address family) during the Socket creation .

2) within the while(1) loop
each time it is advisable to make your readfds empty by using FD_ZERO(&readfds). in the recv() call you should use i rather than clientsocks[i] you have to check return value of recv is negative(which indicating error in reading) if that is the case you do not have to print the message. during printing the message make sure the stdout/server is ready for writing anything to it which you can do it by using writefds (3rd argument of select).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜