【发布时间】:2018-12-28 10:03:52
【问题描述】:
就我而言,我需要在同一台计算机上运行套接字客户端和服务器。
udp socket客户端需要绑定本地端口为1234,并会与 远程端的 socker 服务器。 而同一台计算机上的 udp 套接字服务器也需要将本地端口绑定到 1234,并且还要与远程端的套接字客户端通信。
可行吗?任何潜在的问题或通知? 谢谢!
【问题讨论】:
就我而言,我需要在同一台计算机上运行套接字客户端和服务器。
udp socket客户端需要绑定本地端口为1234,并会与 远程端的 socker 服务器。 而同一台计算机上的 udp 套接字服务器也需要将本地端口绑定到 1234,并且还要与远程端的套接字客户端通信。
可行吗?任何潜在的问题或通知? 谢谢!
【问题讨论】:
如果您使用多播或广播 UDP 通信,那么将多个程序绑定到同一个 UDP 端口通常是有意义的,如果您在调用 bind() 之前使用适当的参数调用 setsockopt(),则可以这样做就可以了:
const int trueValue = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueValue, sizeof(trueValue));
#ifdef __APPLE__
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &trueValue, sizeof(trueValue));
#endif
在这种情况下,端口上接收到的每个多播/广播 UDP 数据包的副本将被传递到绑定到该端口的每个套接字(如果每个程序在单独的机器,因此通常是您想要的)
OTOH,如果您仅发送单播 UDP 数据包(即旨在发送给单个收件人的数据包),那么将多个程序绑定到同一个端口通常没有用,因为您发送的每个 UDP 数据包都将被接收正是一个接收程序和多个程序监听同一个端口,哪个程序将是未指定/不可预测的。例如,在您的情况下,您的客户端程序可能会发送一个数据包,而服务器不会收到它,因为该数据包已排队进入客户端的套接字缓冲区。因此,对于这种情况,您最好让客户端和服务器绑定到不同的端口。 (请记住,任何接收 UDP 数据包的程序都可以通过调用 recvfrom() 来接收数据包并在之后查看 address 参数的内容来轻松找出数据包的发送者绑定到哪个端口;因此它应该即使客户端每次运行时都使用完全随机/任意的 UDP 端口,服务器也可以直接回复客户端发送给它的数据包。如果您告诉客户端将bind() 发送到端口 0,网络堆栈将为其绑定当前可用的 UDP 端口)
【讨论】:
你在用什么?语言、框架、库...
一般来说,服务器正在侦听本地端口。客户端通常会连接到它们并且不会“阻止”它们。所以,从我的角度来看,应该没有问题。
【讨论】:
来自man nc:
CLIENT/SERVER MODEL
It is quite simple to build a very basic client/server model using nc. On
one console, start nc listening on a specific port for a connection. For
example:
$ nc -l 1234
nc is now listening on port 1234 for a connection. On a second console (or a
second machine), connect to the machine and port being listened on:
$ nc 127.0.0.1 1234
【讨论】:
当然客户端和服务器不能绑定到同一个地址。 bind() 函数将返回 -1,perror() 函数将打印“地址已在使用”错误消息。但是为什么需要客户端和服务器绑定到同一个端口呢?通常客户端会选择一个随机端口与服务器通信,或者您可以绑定到与服务器不同的端口。
【讨论】:
不,这是套接字 API 的限制,并且会损害基于 TCP 的对等应用程序的编写。
在对等应用程序中,很自然的做法是为传出和传入连接使用单个端口。虽然 TCP 协议支持此模型,但套接字 API 不支持该模型 — 如果套接字正在侦听端口 p,则将活动套接字绑定到端口 p会失败。
显而易见的解决方法是使用临时端口进行传出连接(不要在活动套接字上使用bind)。这在某些情况下会导致其他问题,需要解决 - 例如,请参阅 BEP-10 中 BitTorrent 扩展握手中的 p 参数。
【讨论】: