连续传输数据的客户端和服务器的最佳套接字选项

时间:2010-07-07 08:09:58

标签: sockets

我正在使用Java(尽管我认为套接字选项是在大多数语言中实现的)来实现客户端和服务器。服务器将数据发送到客户端以进行客户端确认的处理。在另一个端口上,客户端然后将处理结果发送回服务器。当谈到诸如

之类的选项时
  • SO_LINGER
  • SO_KEEPALIVE
  • SO_NODELAY
  • SO_REUSEADDRESS
  • SO_SENDBUFFER
  • SO_RECBUFFER
  • TCP_NODELAY

我们注意到客户端和服务器之间的连接偶尔会中断。发送或接收将超时。发生这种情况时,将终止套接字并打开一个新套接字继续。

根据上述方案设置的最佳选项是什么?我们可以从我们这边做什么(以编程方式或选项方式)来尝试最小化连接被丢弃的次数。我们正在使用普通的TCP / IP。

更新: 对此的赏金很快就会结束。我还没有得到满意的答案,所以它仍然是开放的。我想每个人都错过了这个任务的重点。关于连续聊天的套接字的上述选项的最佳实践是什么?我已经有一个ping数据包,如果没有工作要做(几乎没有情况),正常的消息被发送,没有内部元素,所以总是处理。

6 个答案:

答案 0 :(得分:6)

严格来说,您不需要任何这些套接字选项:

* SO_LINGER

仅当您的应用程序在调用SO_LINGERclose(2)时仍有未完成的数据包发送时,您才需要设置shutdown(2)。不适用于您的应用程序。

* SO_KEEPALIVE

每两个小时发送一次keepalive-ping实际上只会帮助非常长期但非常安静的连接通过具有很长会话超时的状态防火墙。 (ping之间的两个小时对于今天的互联网而言实在是太长了,无法实现。)

* SO_NODELAY

这(可能是TCP_NODELAY的别名)禁用Nagle's algorithm,这只是一个小包避免问题。也许Nagle会妨碍您的应用程序,但它需要特殊的数据包序列才能在处理过程中引入500毫秒的延迟;它永远不会挂起连接。

* SO_REUSEADDRESS

对于侦听众所周知的端口号的所有“服务器”非常有用;在'客户'上使用几乎总是掩盖一些错误或其他错误,但如果请求必须来自一个众所周知的端口号,有时是必要的。

* SO_SENDBUFFER
* SO_RECBUFFER

当程序(接收缓冲区)或套接字(发送缓冲区)尚未准备好接受更多数据时,这些缓冲区大小会影响为接收或发送数据而维护的内核端缓冲区大小。如果这些设置得太小,您的应用程序可能无法尽可能顺利地传输数据,从而降低了吞吐量,但如果设置小于最佳值,则不应导致任何停顿。当然,太大可能会对内核内存提出不合理的要求,但应该有一个合理的系统范围内允许的最大大小。

* TCP_NODELAY

禁用Nagle。如果您的应用程序在尝试阻塞读取之前发送多个小数据包,则不大可能引入500ms延迟。

实际上,您不需要设置任何套接字选项。

您能否将代码提炼成可粘贴在此处并经过测试或检查的内容?我习惯于TCP会话存活数天或数周没有问题,所以这是非常令人惊讶的。

答案 1 :(得分:2)

首先,我认为此页面与半开放连接相关。 http://nitoprograms.blogspot.com/2009/05/detection-of-half-open-dropped.html

话虽如此,TCP旨在隐藏连接问题,因此您可能经常发现自己处于连接断开的情况,但双方都认为不是。您已通过使用超时部分解决了这个问题,并将其视为连接断开的标志。

由于您正在编写客户端和服务器,因此我会避免依赖TCP来告诉您何时完全断开连接。我只是让服务器也确认收到客户端的结果。然后双方都希望立即回复他们的消息,并且您可以跟踪哪些消息已被确认,并设置适当的小超时以接收确认。这不是发送或接收超时,而是发送消息和接收该消息的确认之间的超时。然后,您可以根据连接质量适当地设置超时(例如,如果您在环回上运行则非常小,但如果使用弱信号在无线网络上运行则会很大)。

关于您列出的选项,您将需要使用SO_REUSEADDRESS,这样就不会阻止您重新打开套接字,例如,如果它尚未从先前被杀死的进程中完成关闭。

答案 2 :(得分:1)

你可能有,但最好检查明显的......

您是否确认它是超时的套接字,而不是您的代码?套接字相当稳定,虽然某处可能存在问题,但它似乎更有可能存在于您的代码中。我会使用日志,时间戳和同步时钟来确定。

可能存在一个问题,你真的需要花费很长时间来进行计算,所以可能会在你的协议中添加一个“我还在考虑它”的消息,以便保持连接活着吗? / p>

当然,无论你做什么,网络都会不时退出,听起来你已经很好地处理了这个案例。

答案 3 :(得分:0)

尝试这些选项 SO_LINGER - 用于在Socket关闭s时调用,而队列中有一些未发送的数据 TCP_NODELAY - 用于非阻塞数据传输

答案 4 :(得分:0)

我强烈建议您在客户端和服务器之间使用ping / echo模型,这样如果没有数据发送x秒,则需要发送ping消息。中断的典型原因可能是防火墙,由于不活动而关闭套接字 TCP模型失败的典型问题是物理问题,例如拉断/断开的电缆并悬挂在一侧,技术上有人在监听,直到队列超限开始(根据您的数据量可能永远不会发生)。

答案 5 :(得分:0)

在此过程中某处连接通过NAT防火墙的可能性有多大?状态防火墙维护一个开放连接表,以便属于允许连接的数据包可以快速通过系统,而不必强制防火墙管理员编写过于复杂的规则集。

缺点是这张桌子会变得非常大,所以必须在连接关闭时或者它们似乎已经变得陈旧并且安静地死亡时必须进行修剪。已经沉默20分钟的连接通常很安静,可以收获。 (这真的非常快,因为TCP KEEPALIVE通常是两个小时,这使得它在NAT防火墙面前几乎无用。)

那么:这是通过NAT防火墙吗?连接是否长时间保持安静?如果是这样,请在您的协议中添加ping / pong,并每隔几分钟触发一次。