と思います。しかし、私は保証が何であるか分かりません。
基本的な考え方は次のとおりです。
- 、サーバソケットを作成し、それに
SO_REUSEADDR
を設定し、 サーバポートにバインドし、その上にデータを受信するのを待ちます。
recvfrom
は、次の受信データグラムとそれが送信された のアドレスを示します。
- 初期データグラムとアドレスを新しいスレッドに渡します。
- 新しいスレッドで、新しいソケットを作成します(もう一度
SO_REUSEADDR
でバインドします)。今すぐconnect
ピアアドレスに新しいソケット。
- 戻るここでの考え方は、あなたが常に一つの「未接続」のソケットを維持することである2
進みます。新しいピアを取得すると、そのピアに接続されている新しいソケットが作成されます。ソケットが特にリモートピアに接続されている場合、カーネルはそのピアから受信したデータグラムをそのソケットに渡します。それ以外の場合は、未接続のソケットにデータグラムを配信します。
OSはで、は未接続のソケットではなく、接続されたソケットにしかデータグラムを送信できないのでしょうか?この方法でうまくいくと思いますが、それは私の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))
あなたはできますか?何故なの?新しいスレッドを作成して、必要なものを実行することができます。 –
できます。しかし、そうすることに何らかの利益があることは明らかではありません。単一のスレッドは、単一のソケットを使用して任意の数のUDPクライアントを処理できます。 –
@JeremyFriesner BIOとSSLオブジェクトの周りにあなたのソケットをラップするときにOpenSSLですることができます...私はここでも同じことができるのだろうかと思っていました。 – user2584587