2017-10-05 26 views
0

我知道UDP是無連接的,但是我可以產生一個新線程來處理連接到我的服務器的新UDP客戶端嗎?無法生成一個新的線程來處理一個新的UDP「連接」?

我想基本上做到這一點:

void *handle_connection(void *param) 
{ 
    // read data 
    ret = recvfrom(..,0,..); 
} 


// Wait for connection using MSG_PEEK 
ret = recvfrom(.., MSG_PEEK,..); 

// New thread to handle client connection 
pthread_t conn_thread; 
ret = pthread_create(..., handle_connection); 

有沒有辦法使用時囑咐爲每個客戶端一個UDP「連接」和叉掀起了新的線程來處理它喜歡它是由OpenSSL的做DTLS?

使用OpenSSL,我可以使用DTLS_listen()等待UDP客戶端連接,然後啓動一個新線程,將UDP套接字傳遞給該線程並使用通常的讀/寫操作。爲此,您必須在udp套接字上執行一些額外的bind()和connect()調用。

我在這裏嘗試了相同的方法,結束了爲從服務器上的客戶端接收的每個數據報打開一個新的線程。

+0

你能嗎?爲什麼不?你可以產生新的線程來做你想做的事情。 –

+0

你可以;但是,目前還不清楚這樣做是否有好處。單線程可以使用單個套接字處理任意數量的UDP客戶端。 –

+0

@JeremyFriesner當你將套接字包裝在BIO和SSL對象中時,你可以在OpenSSL中...所以我想知道是否可以在這裏完成相同的工作。 – user2584587

回答

2

我認爲這是可以做到的。但我不確定保證是什麼。

的基本思路是:

  1. 創建服務器插座,在其上設置SO_REUSEADDR,將其綁定到 服務器端口,並等待接收上的數據。
  2. recvfrom爲您提供下一個收到的數據報和它發送的 的地址。
  3. 將初始數據報和地址傳遞給新線程。
  4. 在新線程中,創建一個新的套接字(再次與SO_REUSEADDR綁定)。現在把connect的新套接字給對方地址。
  5. 回到步驟2

這裏的想法是,你始終保持一個「未連接」插座。當你得到一個新的對等體時,你創建一個連接到該對等體的新套接字。當套接字專門連接到遠程對等體時,內核會將來自該對等體的傳入數據報傳遞給該套接字。否則,它會將數據報傳送到未連接的套接字。

我不是100%確定的事情是:操作系統保證只將後續數據報傳遞給連接的套接字而不是未連接的套接字?它是有道理的,它會這樣工作,它似乎在我的Linux機器上工作 - 請參閱下面的python3代碼(可以使用nc -u localhost 9999作爲客戶端)。

#!/usr/bin/env python3 
from threading import Thread 
import socket 

def client_thread(addr, msg): 
    # Create a new socket and connect it to the peer. 
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind(('', 9999)) # Maybe omit -- see below 
    sock.connect(addr) 
    # Maybe set SO_RCVTIMEO to cause timeout on receive and 
    # cause client thread to bail? 
    while True: 
     sock.send(msg) 
     msg = sock.recv(1024) 

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('', 9999)) 

threads = [] 

while True: 
    # Receive datagram on unconnected socket 
    msg, addr = sock.recvfrom(1024) 

    # Send connected socket and datagram 
    th = Thread(target=client_thread, args=(addr, msg)) 
    th.start() 
    threads.append(th) 

你大概會有一些殺死子線程的方式,這樣他們就不會永遠掛在你的客戶端消失了。

或者,您可以省略綁定client_thread中的新套接字,這將導致內核爲新套接字中的本地地址選擇一個未使用的端口,但是客戶端需要注意它的地址收到最初的迴應並將未來的數據報導向該地址。這將完成同樣的事情,並在很多方面變得更清潔。

的客戶端可以是這樣的(再次使用python演示):

#!/usr/bin/env python3 
import socket 

# Initial request sent to well-known port 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
addr = ('localhost', 9999) 

for n in range(5): 
    print('Send to {}'.format(addr)) 
    sock.sendto(b'Hello', addr) 
    response, addr = sock.recvfrom(1024) 
    # Subsequent requests sent to whoever responded to last request 
    print('Got response {} from {}'.format(response, addr)) 
相關問題