Вы также должны bind
сокет на стороне клиента для адреса. Если клиентский сокет привязан (то есть имеет собственное имя), то вам не нужен внеполосный механизм для передачи адреса клиента на сервер. ОС отправляет его вместе с каждой дейтаграммой.
Пример кода для клиента (в python, потому что его легко и быстро создать прототип - его легко перевести на эквивалентный C):
#!/usr/bin/env python3
import os
import socket
server_addr = "/tmp/ux_server"
client_addr = "/tmp/ux_client"
if os.path.exists(client_addr):
os.remove(client_addr)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.bind(client_addr)
for n in range(5):
data = "Hello " + str(n)
data = data.encode()
print("Sent '{}' to {}".format(data, server_addr))
sock.sendto(data, server_addr)
data, addr = sock.recvfrom(16000)
print("Got '{}' back from {}".format(data, addr))
Кроме того, вы можете выполнить connect
на стороне клиента. Поскольку это сокет дейтаграммы, он фактически не создает соединения между ними, но фиксирует адрес конечной точки сервера, освобождая вас от необходимости указывать адрес сервера при каждой отправке (т. Е. Вы можно использовать простой send
вместо sendto
).
Для полноты вот эхо-сервер, соответствующий приведенному выше:
#!/usr/bin/env python3
import os
import socket
server_addr = "/tmp/ux_server"
if os.path.exists(server_addr):
# Bind will fail if endpoint exists
os.remove(server_addr)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.bind(server_addr)
while True:
data, addr = sock.recvfrom(16000)
print("Got '{}' from {}".format(data, addr))
sock.sendto(data, addr)
EDIT
Хм ... Теперь я вижу, что вы говорите, что вы уже
bind
используете сокет клиента, а затем
connect
на стороне сервера. Но это означает, что вам просто нужно, чтобы сервер сначала использовал
recvfrom
один раз для получения адреса клиента. ОС
будет отправлять адрес вместе, и вам не нужно использовать внеполосный механизм.
Недостатком подключения сокета является то, что если клиент выйдет из строя, сервер не узнает об этом, пока не попытается отправить, но клиент не сможет восстановить соединение, поскольку сокет сервера уже подключен. Вот почему серверы дейтаграмм обычно используют recvfrom
и sendto
для всех сообщений.
Обновлен сервер с начальным recvfrom
, за которым следует connect
:
#!/usr/bin/env python3
import os
import socket
server_addr = "/tmp/ux_server"
if os.path.exists(server_addr):
# Bind will fail if endpoint exists
os.remove(server_addr)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.bind(server_addr)
client_addr = None
while True:
if client_addr:
data = sock.recv(16000)
else:
data, client_addr = sock.recvfrom(16000)
sock.connect(client_addr)
print("Got '{}' from {}".format(data, client_addr))
sock.send(data)
Обновлен клиент с подключенным сокетом.
#!/usr/bin/env python3
import os
import socket
server_addr = "/tmp/ux_server"
client_addr = "/tmp/ux_client"
if os.path.exists(client_addr):
os.remove(client_addr)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.bind(client_addr)
sock.connect(server_addr)
for n in range(5):
data = ("Hello " + str(n)).encode()
print("Sent '{}'".format(data))
sock.send(data)
data = sock.recv(16000)
print("Got '{}' back".format(data))