如何创建持久的TCPSockets?

我有一台服务器连续向客户端发送两条消息:

require 'socket' require 'thread' connections = [] server = TCPServer.new(9998) loop do Thread.start(server.accept) do |client| client.print 'Once' client.print 'Upon a time.' end #eo Thread end #eo infinte loop 

客户是:

 require 'socket' client = TCPSocket.new('localhost', 9998) 2.times { print client.read } client.close 

客户端“暂停”,直到我关闭服务器,然后才打印出消息。 我知道将client.close添加到服务器会修复暂停,但我不想关闭套接字。

我知道一些应用程序重用TCPSocket。 因此,它可以是Client > ServerServer > ClientClient > Server x2 ,依此类推。 我相信在Ruby中有办法做到这一点; 我只是无法弄清楚如何。

所以,我的问题清单是:

  1. 如上所述,如何创建持久性服务器客户端连接?
  2. 是否有更好的方法可以在不使用loop情况下保持服务器打开?
  3. 为什么它会像服务器中没有client.close那样保持暂停状态? 服务器在发送消息之前是否缓冲消息?

  1. 如上所述,如何创建持久性服务器< - >客户端连接。

你有几个选择:你可以编写一个线程服务器,其中一个主要是共享内存的“进程”执行多个执行线程,每个线程都有一些线程本地存储,例如client 。 或者,您可以编写一个多进程服务器,其中每个客户端连接通过fork(2)获得其自己的独立进程(这几乎意味着它仅在Unix上运行,因为Windows尝试实现fork(2)永远不会正常工作) 。 或者,您可以编写基于事件循环的状态机,并使用select(2)poll(2)epoll(4)来管理哪些客户端是可读,可写和有错误的。

在他们之间进行选择可能看起来很困难, 但有指导方针可供选择 我想建议-small-系统,你只需要20-30个并发客户端,可以通过线程或分叉服务器很好地处理。 如果您希望超越同时数量的客户端,则应使用EventMachine或libevent等工具编写服务器。 (无论如何,这可能会或可能不会更容易维护。)

2)有没有更好的方法来保持服​​务器打开,而不使用循环[因为我觉得我通过创建无限循环犯下谋杀]

无限循环非常好:)但有时提供重启服务器或通过signal(7)或专用命令接口终止它们的方法是有意义的。

3)为什么它在服务器中没有client.close的情况下保持暂停状态? 服务器在发送消息之前是否缓冲消息?

啊, 是你真正需要的问题 – TCP将尝试缓冲来自服务器的多个数据包的结果,并且由于可能需要在路由中分割太大的数据包,作为客户端,您无法保证保留任何类型的数据报边界。

在发送第一个数据包以查看是否即将推出更多数据之前,您的服务器的TCP / IP堆栈会等待一小段机会非常好。 (它经常这样做。)它可能将对client.print()两次调用合并为一个TCP数据包。 您的客户端调用client.read() 两次 ,但一次读取可能只有足够的数据。 如果您希望TCP流立即发送第一个数据包,您可以查看设置TCP_NODELAY套接字选项以禁用此小延迟。 (但它本身可能没有帮助;你可能需要与TCP_CORK一起使用它来尝试“ TCP_CORK ”所有写入,直到你明确刷新它们。这可能是一个糟糕的主意。)

更好的选择是重新编写客户端以了解服务器和客户端之间的协议 ; 它需要将输入读入缓冲区,解析缓冲区以查找“完整消息”,使用这些消息,然后返回其主事件循环。

也许你的协议是读/写ASCII或以"\n"字符终止的UTF-8; 在这种情况下,您可以将print更改为puts或将\n添加到正确的位置,并将read()更改为readline() 。 (这将让标准IO库为您处理协议。)另一种方法是发送长度为+数据对的数据,并等待正确的数据长度。

请改用put。 如果你想男性确定发送它,请使用socket.flush。 否则它会缓冲数据。