如何在套接字编程中处理多个客户端?

时间:2017-08-02 10:05:39

标签: c sockets network-programming

我是套接字编程的新手。我正在尝试制作简单的客户端,服务器程序,其中从客户端发送的消息出现在服务器窗口上。但它只适用于一个客户端。如何处理多个客户端。提前致谢。 这是我的代码
Server.c

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

#define ERROR -1
#define MAX_DATA 1024

int main(){
  int welcomeSocket, newSocket;
  char buffer[MAX_DATA];
  int data_len;
  struct sockaddr_in serverAddr;
  int addr_size = sizeof(struct sockaddr_in);

  if((welcomeSocket = socket(PF_INET, SOCK_STREAM, 0)) == ERROR){
    printf("Socket: ");
    exit(-1);
  }
  /* Configure settings of the server address struct */
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(9999);
  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  /* Set all bits of the padding field to 0 */
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /* Bind the server address struct to the socket */
  bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

  /* Listen on the socket, with 5 max connection requests queued */
  if(listen(welcomeSocket,5) == 0)
    printf("Listening\n");
  else
    printf("Error\n");

  while(1){
    /* Accept call for the incoming connection */
    if((newSocket = accept(welcomeSocket, (struct sockaddr *)&newSocket, &addr_size)) == ERROR){
      perror("accept");
      exit(-1);
    }
    data_len = 1;
    while(data_len){
      /* receive msg and print */
      data_len = recv(newSocket, buffer, MAX_DATA, 0);
      if(data_len){
        buffer[data_len] = '\0';
        printf("%s\n", buffer);
      }
    }
  }
  printf("Client Disconnected\n");
  close(newSocket);

  return 0;
}

2 个答案:

答案 0 :(得分:0)

您可以使用多线程同时管理多个客户端,因此服务器可以在等待接收每个客户端消息的同时“同时”侦听新连接。

当您的服务器呼叫accept()时,如果没有客户端加入,则该呼叫将“阻止”执行,直到有人加入。

然后,出于同样的原因,recv()的调用将阻止主线程,直到客户端发送消息为止。

使用多线程会导致阻止recv()accept()不会影响主线程。

答案 1 :(得分:0)

有几种策略可以处理服务器上的多个clinets。 首先是使用线程,这意味着为每个新客户端分配一个新线程并处理其所有流量。这样,主线程不会被读/写或rec / send系统调用阻塞,并且可以自由处理新的incomming客户端。 第二种策略是使用非阻塞I / O,这比第一种策略稍微困难,但它在性能和资源消耗方面都相当不错。 第三种策略是为每个客户使用一个唯一的端口号,一些商业程序使用这种策略,但我没有个人建议。如果我要编写一个服务器应用程序,我已经完成了比计算更多的服务器应用程序,我会选择非阻塞I / O,尽管在最初的几次尝试中它很难让它工作,但它是非常值得的,并且比任何其他策略更好地工作。 搜索非阻塞I / O并选择()以获得更进一步的指令