【发布时间】:2017-02-11 09:00:20
【问题描述】:
我在包括这里在内的所有地方搜索了可能的解决方案,并尝试了一些我找到的答案,但没有成功。
我实现了一个简单的 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)
【问题讨论】:
-
您确定他们使用 Big Endian 发送吗?一些 C 程序假定小端,
-
当您尝试运行客户端时实际发生了什么?
-
服务器使用什么协议进行回复?它是在字节级别记录的吗?如果您不知道服务器期望它做什么,您怎么可能知道您的客户端是否在做正确的事情? (您有协议文档吗?或者您需要对协议进行逆向工程吗?如果您有协议文档,请分享。如果您需要对协议进行逆向工程,请向我们展示服务器发送给您的字节,以便我们尝试帮助您这样做。)
-
(RST 发生是因为您没有遵循服务器期望您遵循的协议,读取的数据少于发送的数据。)
-
回答彼得的问题,这是我首先关心的问题之一,但服务器的开发人员说字节序应该是正确的。此外,我们有相反的沟通方式。我有一个 Java 服务器,他有一个运行相同协议的 C 客户端,这非常有效。我能够阅读和解析他的请求,我可以发送他得到的回复。我假设协议中是否存在一些不兼容,如果我的 Java 应用程序尝试从 C 应用程序读取传入流,则另一种方式的通信会在连接被重置时遇到类似的问题。
标签: java sockets tcpclient tcpserver