简体   繁体   English

建立连接后,Java套接字读未接收到发送的写操作

[英]Java socket read not receiving write sent immediately after connection is established

I have a java client and server I'm trying to write Junit tests. 我有一个Java客户端和服务器,我正在尝试编写Junit测试。 In my tests I wait for a connection between the server and client to be made, and then write a message to from server to client to test the communication. 在测试中,我等待服务器和客户端之间建立连接,然后将一条消息从服务器发送到客户端以测试通信。 I've discovered if I do the write immediately It isn't received and the client stays blocked on the BufferedReader.readLine() method. 我发现我是否立即进行写操作,但仍未收到,并且客户端在BufferedReader.readLine()方法上保持阻塞状态。 If I add a sleep for half a second between the socket connection and the server write call everything works perfectly. 如果我在套接字连接和服务器写调用之间添加了半秒的睡眠,则一切运行正常。

I'm trying to figure out why the sleep is needed. 我试图弄清楚为什么需要睡眠。 I know that the socket has been generated and a bufferedReader wrapped around it's input stream before my waitForConnection() method returns with a report that server and client have connected. 我知道套接字已经生成,并且在我的waitForConnection()方法返回带有服务器和客户端已连接的报告的返回值之前,已将套接字的输入流包裹着bufferedReader。 My best guess is that I need to ensure that I call the readLine method of the client before the server calls it's write method; 我最好的猜测是,我需要确保在服务器调用客户端的readLine方法之前,先调用客户端的readLine方法。 but I thought that sockets would automatically buffer input that came in and wasn't read immediatly? 但我以为套接字会自动缓冲传入的,不是立即读取的输入?

Can anyone confirm (or disprove) my suspicion that I have to guarantee the client has called readline before the server calls write. 任何人都可以确认(或驳斥)我的怀疑,即我必须保证客户端在服务器调用write之前已调用readline。 And if this is required can anyone suggest a way that the server can detect if the client is ready to receive input without having to implement another handshake in addition to the TCP handshake? 并且如果需要这样做,谁能提出一种方法,使服务器可以检测客户端是否准备好接收输入,而无需执行除TCP握手之外的其他握手?

edit: I should have said this sooner, but the test that is failing is testing an ability to restablish a connection when the old one fails. 编辑:我早该说过了,但是失败的测试是测试当旧的失败时重新建立连接的能力。 After the client connects my mock server kills the socket/serverSocket and a few seconds later reopens a new serverSocket and accepts a new connection from the client. 客户端连接后,我的模拟服务器杀死了socket / serverSocket,几秒钟后重新打开了一个新的serverSocket并接受了来自客户端的新连接。 It's after the client establishes a connection for the second time that the write failes. 客户端第二次建立连接之后,写入才会失败。 My earlier tests that just test a connection occures and the client receives a write appear to work. 我的较早测试仅测试连接,并且客户端收到写操作似乎起作用。

Thanks 谢谢

Can anyone confirm (or disprove) my suspicion that I have to guarantee the client has called readline before the server calls write. 任何人都可以确认(或驳斥)我的怀疑,即我必须保证客户端在服务器调用write之前已调用readline。

You don't. 你不知道 The server can send any time it likes. 服务器可以根据需要发送任何时间。

And if this is required 如果需要的话

It isn't. 不是。

Your problem lies elsewhere. 您的问题出在其他地方。

I had the same problem and even thought about a cumbersome acknowledgement process. 我遇到了同样的问题,甚至想到了一个麻烦的确认过程。 But in fact you do not need to wait for the read to get called and the problem is located somewhere else. 但是实际上,您不需要等待read调用就可以解决问题了。

In my case the I delegated the reading call to a separate thread. 就我而言,我将read调用委托给了一个单独的线程。 But the jUnit test was finishing successfully although the read in the thread 但是尽管线程中进行了read ,但jUnit测试已成功完成

  • didn't get called yet, 还没接到电话
  • was still in reading process or 仍在阅读过程中或
  • even worse: the thread didn't even reach running state 更糟糕的是:线程甚至没有达到运行状态

when the main jUnit-Thread already terminated. 当主jUnit-Thread已终止时。

To prove my assumption you could put the wait at the end of the unit test instead "between the socket connection and the server write call" and the sending/receiving will still work. 为了证明我的假设,您可以将等待放在单元测试的末尾,而不是“在套接字连接和服务器写调用之间”,发送/接收仍然可以进行。

Just for completeness: do not forget to call flush() 仅出于完整性考虑:不要忘记调用flush()

You do not need to make sure the client is reading before server writes. 您无需在服务器写入之前确保客户端正在读取。 The network layer will buffer the traffic until it is consumed. 网络层将缓冲流量,直到流量被消耗为止。

Make sure to call flush on the OutputStream after issuing the message on the server. 在服务器上发出消息后,请确保在OutputStream上调用flush。 Otherwise, actual network call may not be made until buffer fills up. 否则,在缓冲区填满之前可能无法进行实际的网络调用。 Also, your use of readLine may be problematic. 另外,您对readLine的使用可能会出现问题。 Perhaps you aren't issuing line termination character? 也许您不是在发出行终止符? It may be better to use the more basic read( char[] ) method. 最好使用更基本的read(char [])方法。

How you destroy the server socket in your unit test? 如何在单元测试中销毁服务器插槽? May be you close the socket before the data is sent. 可能是您在发送数据之前关闭了套接字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM