【问题标题】:Multi-threaded udp server/client多线程 udp 服务器/客户端
【发布时间】:2011-04-06 12:56:24
【问题描述】:

我刚刚使用 udp 创建了一个可靠的文件传输,但它只处理一个客户端。所以我考虑使用 fork() 让服务器处理多个客户端。但是,我真的不知道如何进行。现在,我知道我不需要更改客户端,而服务器将完成这项肮脏的工作。非常感谢有关如何解决该问题的任何想法/想法。 附言。我是这样开始的:

 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 函数会处理所有传入的数据。

【问题讨论】:

    标签: c udp fork


    【解决方案1】:

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

    如果您要分叉,您需要执行 ftpd 的操作,并告诉远程客户端在与原始端口不同的端口上发送分叉的子数据包(当然让子数据包在该端口上接收) )。

    【讨论】:

    • 那么在 udp 中不可能让所有客户端都运行在同一个传入端口上?
    • @fabricemarcelin - 你可以,但它会变得复杂。您可以使用 recvfrom() 获取源地址(客户端)并将它们分开。但是,如果您在同一个端口上分叉子节点,如何阻止第一个子节点从客户端#2 读取初始数据报? TCP 会为您解决这个问题,因为 accept() 在幕后创建了一个新套接字。
    • @Duck - 快速提问。如果我在套接字上 fork,我怎么知道新的端口号作为参数传递给客户端?
    • @fabricemarcelin - 您的服务器通过在绑定中指定 0 作为端口号来请求临时端口。然后,您可以通过调用 getsockname() 来获取分配的端口。
    【解决方案2】:

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

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

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

    【讨论】:

    • 您能否提供一些伪代码或指向这样的示例。谢谢
    猜你喜欢
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 2014-12-21
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多