我到处搜索,包括可能的解决方案,并尝试了一些我找不到的答案。
我实现了一个简单的Java tcp套接字客户端。客户端在一台Java服务器上工作得很好但是我一直在接收来自用C编码的服务器的响应时遇到问题。 服务器似乎正在正确处理事务,并相应地发送回复。问题在于客户端能够接收回复的传入流。 这是我最初的实施:
String msg_out = message;
String reply;
//the stream object to transmit message to server
DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream());
outStream.writeBytes(msg_out + '\n');
outStream.flush();
//try to break away from locked read
//clientSocket.setSoTimeout(10000);
//initial implementation
//the object to receive reply server
BufferedReader replyStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
reply = replyStream.readLine();
System.out.println("Reply from "+ host + ":" + port + " -> " + reply);
我下载了Wireshark并用它来监视服务器套接字正在侦听的相应端口中客户端和服务器之间的tcp数据包流量。我在其他主题中看到了类似主题的多个建议,遗憾的是我无法让任何这些解决方案适合我。我发现包含回复的数据包的标志值设置为PSH(在接收时不要缓冲蒸汽,立即处理)。我认为Java客户端通过尝试缓冲响应导致连接重置(出现在故障数据包中的RST,这是下一个发生的),因为这个标志。我尝试使用这个实现进行测试,我在一个线程中发现这里尝试逐字节读取回复,但无济于事:
try {
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
byte[] messageByte = new byte[1000];
boolean end = false;
String messageString = "";
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);
int bytesToRead = byteBuffer.getShort();
System.out.println("About to read " + bytesToRead + " octets");
//The following code shows in detail how to read from a TCP socket
while(!end)
{
bytesRead = in.read(messageByte);
messageString += new String(messageByte, 0, bytesRead);
if (messageString.length() == bytesToRead )
{
end = true;
}
}
System.out.println("Server Reply: " + messageString);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
我无法访问C服务器的源代码,但它的开发人员向我发誓,问题不在他的最后,我相信他。我也知道他不能对它进行更改,因为它适用于所使用的每个其他客户端体系结构,我编码的那个恰好是与这个基于C的服务器交互的唯一Java客户端。我的实现中是否有错误,或者是否有其他实现可以用来以更加万无一失的方式读取回复流?
这是尝试运行客户端/服务器通信过程的结果:
[2/10/17 14:23:49:658 EST] 00000031 SystemOut O Outgoing transaction message:C00052!GDT43000KU!01!D-10!G-11!NORMAL!|
[2/10/17 14:23:49:658 EST] 0000011e SystemOut O Buffersize in stream:8192
[2/10/17 14:23:49:737 EST] 0000011e SystemOut O About to read 12336 octets
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R java.net.SocketException: Connection reset
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at java.lang.Throwable.<init>(Throwable.java:67)
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at java.net.SocketInputStream.read(SocketInputStream.java:118)
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at java.io.DataInputStream.read(DataInputStream.java:94)
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at com.gf.btv.RTDLTSS.domain.LTSSClient.TCPClientRequest(LTSSClient.java:141)
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at com.gf.btv.RTDLTSS.helper.LTSSClientThread.run(LTSSClientThread.java:147)
[2/10/17 14:23:49:737 EST] 0000011e SystemErr R at java.lang.Thread.run(Thread.java:736)
答案 0 :(得分:0)
RST与PSH或缓冲的阅读器没有任何关系,但如果你需要阅读二进制文件,那么阅读器是不合适的。 RST表示对等方在您读取连接之前关闭了连接,这表明您使用了错误的协议。请求协议是基于行的,但响应协议是基于长度字前缀的,这是不可信的。一个或另一个,或其他东西。
如果您确定它确实是长度字前缀协议,请尝试以下方法:
int messageLength = in.readShort();
byte messageBytes = new byte[messageLength];
in.readFully(messageBytes);
// etc.
但是你需要确认实际的协议。 Guesswork不会让你到那儿。