Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 为什么重新绑定到套接字会随机失败?_Sockets_Haskell_Networking - Fatal编程技术网

Sockets 为什么重新绑定到套接字会随机失败?

Sockets 为什么重新绑定到套接字会随机失败?,sockets,haskell,networking,Sockets,Haskell,Networking,这个问题与,其中我包括了一个getFreePort函数,该函数检索第一个可用端口。此函数在Windows系统上工作,但当我在Linux机器上尝试时,它会随机失败(空闲端口报告为繁忙) 我修改了函数以尝试重新绑定到空闲地址,但它随机失败: getFreePort :: IO Integer getFreePort = do sock <- socket AF_INET Stream defaultProtocol bind sock (SockAddrInet aNY_PORT iN

这个问题与,其中我包括了一个
getFreePort
函数,该函数检索第一个可用端口。此函数在Windows系统上工作,但当我在Linux机器上尝试时,它会随机失败(空闲端口报告为繁忙)

我修改了函数以尝试重新绑定到空闲地址,但它随机失败:

getFreePort :: IO Integer
getFreePort = do
  sock <- socket AF_INET Stream defaultProtocol
  bind sock (SockAddrInet aNY_PORT iNADDR_ANY)
  port <- socketPort sock
  close sock
  print "Trying to rebind to the sock"
  sock <- socket AF_INET Stream defaultProtocol
  bind sock (SockAddrInet port 0x0100007f)
  port <- socketPort sock
  close sock
  return (toInteger port)
getFreePort::IO整数
getFreePort=do

sock一般来说,
检查资源是否可用,如果可用,则接受资源通常是一种反模式。无论何时这样做,您都会面临另一个进程在检查之后但在您自己实际获取资源之前获取资源的风险

在这样一次检查之后,您得到的唯一信息是资源在特定的时间点没有被使用。它可能会也可能不会帮助您猜测端口未来的状态,但您拥有的信息在以后任何时候都不会有任何约束力。您不能假设,因为资源在时间
t
时是空闲的,所以它在时间
t+dt
时仍然是空闲的。即使
dt
非常小。当你要求快一点的时候,它可能还是免费的。但这只是它-可能是一个更高的概率

您应该尝试获取资源并适当地处理故障。确保端口真正可用的唯一方法是您刚刚成功打开它。那你就知道它确实是免费的。一旦你结束,所有的赌注都将再次落空

我认为您永远无法安全地检查一个端口在一个进程中是否空闲,然后假设它在另一个进程中仍然空闲。这没有道理。在同一个过程中,它甚至没有意义

至少你必须设计一个来回的协议:

  • 这是一个免费的端口,试试看
  • 不,现在有人了
  • 好的,这是另一个
  • 不,现在有人了
  • 好的,这是另一个
  • 是的,知道了,谢谢

  • 但从一开始这就很愚蠢。需要端口的进程应该只打开它。如果它已经打开了端口,而不是之前,那么它应该将端口号告知另一方。

    在获得空闲端口后,为什么要关闭用于获取该端口的套接字?不要那样做。只需使用相同的套接字,不要创建新的套接字并将其绑定到同一端口,这确实是一种竞争条件。关闭上一个套接字会使端口进入
    TIME\u WAIT
    状态,这会阻止它在一段时间内被重用,除非您使用
    SO\u REUSEADDR
    /
    SO\u REUSEPORT
    套接字选项问题是我必须将端口号传递给将在该端口上通信的两个外部进程。这就是为什么我必须关闭它。为什么这两个进程不能为自己获得端口并相互协调?你为什么要在第三个过程中这样做?您无法获取端口,然后关闭它,然后期望进程能够使用它。你需要重新考虑你的方法。是的,这听起来很有道理。但这是两个过程的设计方式。它们需要一个相互通信的端口号。我不能改变这一点。另一种方法可能是在某个范围内分配一个随机端口号。