2012-05-21 124 views
4

是否有可能通過2個端口上的recvfrom接收數據?我有一個端口用於用戶請求,另一個端口用於聊天消息。是否有可能綁定兩個套接字,使用不同的端口並通過一個recvfrom()接收數據?UDP在多個端口上接收數據

問候

編輯 這是否代碼工作?

int socket_fd,socket_fd2; 
struct sockaddr_in addr, chat_addr; 

addr.sin_family = AF_INET; 
addr.sin_port = htons(1234); 
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

chat_addr.sin_family = AF_INET; 
chat_addr.sin_port = htons(4321); 
chat_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

bind(socket_fd2, (struct sockaddr *) &chat_addr, sizeof(struct sockaddr_in)); 
bind(socket_fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)); 

所以我想在兩個不同的端口上接收數據。

回答

3

不,不可能使用一個調用recvfrom從兩個套接字讀取,因爲該函數只接受一個套接字文件描述符參數。

您可能需要每個端口的線程或機制(例如selectpoll)來確定哪些套接字有數據等待讀取。

在後一種情況下,一旦你知道哪些套接字你然後呼叫recvfrom對特定的套接字待處理的數據可以得到你所需要的數據,例如:

// set up select parameters 
fd_set socks; 
FD_ZERO(&socks); 
FD_SET(socket_fd, &socks); 
FD_SET(socket_fd2, &socks); 

// find out which sockets are read - NB: it might be both! 
int nsocks = max(socket_fd, socket_fd2) + 1; 
if (select(nsocks, &socks, (fd_set *)0, (fd_set *)0, 0) >= 0) { 
    if (FD_ISSET(socket_fd, &socks) { 
      // handle socket 1 
      recvfrom(socket_fd, ...); 
    } 
    if (FD_ISSET(socket_fd2, &socks) { 
      // handle socket 2 
      recvfrom(socket_fd2, ...); 
    } 
} 

注意:這僅僅是一個粗糙和準備好的樣本 - 真實的代碼將有錯誤檢查等。

+0

所以我需要將兩個套接字綁定到我的服務器並使用例如select? – user1324258

+0

如何在使用select接收數據時獲取發件人地址? – user1324258

+0

您不會使用select()接收數據,而select()會告訴您哪個套接字有數據準備好讀取,然後像平常一樣使用recvfrom()讀取數據。 –

2

使用select/poll方法的答案適用於UDP。

我之前的回答是一個錯誤,因爲有一段時間我被我的工作代碼搞糊塗了,現實生活中的工作代碼是使用無端口協議(如ICMP等)。

但是,回到UDP這一切都取決於你是哪一方,服務器或客戶端。

當您發送UDP數據包時,您通常會將使用的端口綁定到套接字,或者在使用sendto()發送數據時自動爲其分配臨時端口。所以,通常以後你可以調用recvfrom()來接收一個回覆,通常回發給你的套接字的端口,該端口被綁定或分配。在這種情況下,您可以使用單個本地套接字和單個本地端口與兩個(以及更多)不同的遠程地址和端口組合進行通信 - 想想類似於反向服務器:-)

另外,在協議和系統功能上,您可以使用兩個套接字作爲一個端口,或者使用兩個套接字作爲無端口協議(如ICMP) - 在這種情況下,每個套接字都應接收其自己的數據副本。

以上只是有趣的,不實用。

對您而言,實用的解決方案甚至不是上面提出的兩個套接字之間的選擇/輪詢建議,而是通過內部協議設計分隔的單個套接字 - 例如,將通道標識符等內容放入數據包中,您將保存端口堆棧。

+0

這個答案仍然是錯誤的。單個套接字FD _cannot_接收數據發送到多個UDP端口。 – Alnitak

相關問題