首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >针对不良网络的套接字编程

针对不良网络的套接字编程
EN

Stack Overflow用户
提问于 2014-01-23 15:24:21
回答 2查看 1K关注 0票数 1

客户端:

代码语言:javascript
运行
复制
socket(), connect() and then 
for (1 to 1024) { 
   write(1024 bytes)
}
exit(0);

服务器:

代码语言:javascript
运行
复制
socket(), bind(), listen()
while (1) {
  accept()
  while((n = read()) {
     if (n == -1) abort(); /* never happended */
     total_read += n
  }
  close()
}

现在,客户端运行在NAT下的Mac上,服务器运行在我的VPS (国外)上

一般来说,它工作得很好(客户端发送所有数据,然后退出&服务器接收所有数据)

然而,当客户端正在运行,但突然网络中断了几分钟(然后又恢复)时,客户端在很长很长时间后不会退出……我用more +C终止它,然后再次运行它,服务器似乎不再读取数据(客户端仍在运行)

以下是netstat显示的内容:

客户端:

代码语言:javascript
运行
复制
tcp4       0 130312  192.168.1.254.58573    A.B.C.D.8888    ESTABLISHED

服务器:

代码语言:javascript
运行
复制
tcp        0      0 A.B.C.D:8888     a.b.c.d:54566      ESTABLISHED 10970/a.out     
tcp   102136      0 A.B.C.D:8888     a.b.c.d:60916      ESTABLISHED - 

A.B.C.D是我的VPS地址。a.b.c.d是我的公共客户端地址

我的问题是:

1,为什么?

2、服务器重启后工作正常,如何编写代码摆脱重启?

EN

回答 2

Stack Overflow用户

发布于 2014-01-23 15:31:53

在TCP中,除非您尝试在连接上发送某些内容,否则无法判断连接已失败。TCP不对连接执行主动监控(实际上,有可选的"keepalive“数据包,但这些数据包通常在连接空闲几个小时后才会发送)。当你发送一些东西时,如果等待另一台机器返回确认超时,你最终会得到一个错误。但是,如果您只是读取数据而不发送数据,则无法断定连接已失败--只是看起来发送方没有要发送的内容。

您可以通过将应用程序设计为要求客户端每N秒发送一次内容来解决此问题。然后在服务器中设置一个计时器,该计时器会检测到您已经超过N秒没有收到任何东西(您应该增加一点额外的时间,以考虑到短暂的延迟)。

票数 4
EN

Stack Overflow用户

发布于 2014-01-24 05:06:42

当网络中断时,发生的情况是您的客户端不断发送数据,并且在某个时候套接字发送缓冲区变满(我从您显示的内容中了解到,您正在发送1024个字节,1024次,总共1MB )。发送缓冲区的默认值可以是16KB (肯定小于1MB)。然后,当客户端尝试写入时,它将永远被阻塞。

顺便说一句,现在我在回答你的问题,我不知道在TCP超时之后,TCP是否最终放弃并关闭套接字,使套接字接口返回错误。我认为这不会发生... :) -因此,如果网络中存在问题,连接将失败,但写入和读取不会失败。

在服务器端,服务器在读取时被阻塞,因为它从未接收到EOF。

解决方案:

在客户端使用非阻塞套接字时,如果网络中断,write将返回错误EWOULDBLOCK。然后你就会意识到由于某种原因发送缓冲区已经满了。此时,您可以单击该连接,然后再次尝试连接。如果网络断开,您将收到一个错误。

在服务器端,也可以使用非阻塞套接字和带有超时的select()函数。在几次超时之后,您可能会确定新连接存在问题,并将其关闭。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21301854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档