2011-04-06 290 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