2011-04-06 161 views
3

我刚刚使用udp创建了一些可靠的文件传输,但它只处理一个客户端。所以我想过使用fork()来让服务器处理多个客户端。但是,我不知道如何继续。就目前而言,我知道我不需要改变客户端,而服务器就是做那些肮脏工作的人。任何关于如何解决这个问题的想法/想法都是非常感谢的。 Ps。这里是我是如何开始的:多线程udp服务器/客户端

void sigchldAction(int sig) { 
while (waitpid(-1, 0, WNOHANG) > 0) { 
    ; 
}int main(int argc, char *argv[]) { 

return; 
} //This is my function that waits for all the processes 

这里是我的服务器:

int main(int argc, char *argv[]) { 
    struct sockaddr_in serv_addr; 
    int port_number, socket_fd; 
    port_number = atoi(argv[1]); 

    signal(SIGCHLD, sigchldAction); 

    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(EXIT_FAILURE); 
    if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, 
(const void *)&optval, sizeof(int)) < 0) exit(EXIT_FAILURE); 

    bzero((void *)&serv_addr, sizeof(struct sockaddr_in)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(port_number); 
    if (bind(socket_fd, (struct sockaddr *)&serv_addr, 
     sizeof(struct sockaddr_in)) < 0) exit(EXIT_FAILURE); 

    pid_t child_pid; 
    while (1) { 
    child_pid = fork(); 

    switch (child_pid) { 
     case -1: 
      perror("Fork() Failed. \n"); 
      exit(EXIT_FAILURE); 
      break; 
     case 0: 
      process_request(socket_fd); 
      exit(EXIT_SUCCESS); 
      break; 
     case 1: 
      close(socket_fd); 
      break; 

    } 

} 
    close(socket_fd); 
exit(EXIT_SUCCESS); 
} 

然后我process_request函数接受任何输入数据的照顾。

回答

4

如果你使用UDP,你没有连接;这是一个无连接协议。

如果你要分叉,你需要做ftpd所做的事情,并告诉远程客户端在不同于原始端口的端口上发送分叉子数据包(当然,让孩子接收该分组港口)。

+0

所以在udp中不可能让所有客户端运行在同一个传入端口上? – fabricemarcelin 2011-04-06 02:17:54

+2

@fabricemarcelin - 你可以但它会变得复杂。您可以使用recvfrom()获取源地址(客户端)并将它们分开。但是如果你在同一个端口上为孩子们分配什么东西来阻止第一个孩子读第二个客户端的初始数据报? TCP为你排序,因为accept()在封面下创建一个新的套接字。 – Duck 2011-04-06 03:09:13

+0

@Duck - 虽然有疑问。如果我在套接字处分叉,我将如何知道新的端口号作为参数传递给客户端? – fabricemarcelin 2011-04-06 03:23:04

1

您最好避免fork(),并根据其源地址区分客户端。

要采取的基本方法是采取当前描述应用层连接的所有变量(例如,当前文件,文件中的当前位置,客户端地址)并将其提升到struct。然后,您为每个客户创建一个这种struct的实例。

使用recvfrom()而不是recv()侦听传入数据包。这将提供客户端的地址(请注意,这种意义上的地址应包含客户端的端口号) - 然后您可以查找每个客户端的合适实例struct

+0

你能否提供一些伪码或指向这样的例子。谢谢 – m4n07 2013-03-29 02:14:50