Java TCP数据包接收的不确定状态
解聚环境: 我已经在Windows10操作系统上使用JAVA创建了一个TCP服务器。我的TCP客户端程序是用VC++编写的,运行在Windows7操作系统上(我对这部分代码没有任何控制权,它对我来说是一个黑匣子) 我的TCP服务器代码如下:Java TCP数据包接收的不确定状态,java,windows,sockets,networking,tcp,Java,Windows,Sockets,Networking,Tcp,解聚环境: 我已经在Windows10操作系统上使用JAVA创建了一个TCP服务器。我的TCP客户端程序是用VC++编写的,运行在Windows7操作系统上(我对这部分代码没有任何控制权,它对我来说是一个黑匣子) 我的TCP服务器代码如下: Socket s = ss.accept(); s.setReceiveBufferSize(2000); s.setSendBufferSize(2000); s.setTcpNoDelay(true); s.setKeepAlive(true); new
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
以下是TCP连接处理程序片段:
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
通信基于数据包,协议/解析由packetHandler
处理
我又尝试了两种变体:
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
read
方法之前,我使用了inputStream.available
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
大多数情况下,TCP服务器会在一秒钟内回复传入的数据包。如果服务器在空闲时间后收到数据包,则服务器不会回复该数据包。有时,即使正在进行主动通信,也不会发送回复。其次,isConnected
函数返回true,即使客户端套接字关闭了连接
调试尝试:
Socket s = ss.accept();
s.setReceiveBufferSize(2000);
s.setSendBufferSize(2000);
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
InputStream incomingPacketBuffer = this.clientSocket.getInputStream();
OutputStream outgoingPacketBuffer = this.clientSocket.getOutputStream();
int bufferLen=0;
byte inBuffer[] = new byte[this.clientSocket.getReceiveBufferSize()];
byte outBuffer[] = new byte[this.clientSocket.getSendBufferSize()];
while(this.clientSocket.isConnected())
{
bufferLen = incomingPacketBuffer.read(inBuffer);
if(bufferLen>0)
{
outBuffer = (byte[]) this.packetHandlerModule.invoke(this.packetHandler,Arrays.copyOf(inBuffer, bufferLen));
}
if(outBuffer != null)
{
if(this.clientSocket.isConnected())
{
outgoingPacketBuffer.write(outBuffer);
outgoingPacketBuffer.flush();
}
}
}
this.clientSocket.close();
setKeepAlive
设置为true(从服务器发送数据包时没有问题)有些事情要考虑;
- TCP缓冲区的大小通常至少为8K,我不认为可以将它们压缩到2000字节,或者如果可以,我认为这不是一个好主意
的大小在2K左右并不重要,您不妨选择一个值字节[]
- 您不需要多次创建缓冲区
Socket s = ss.accept();
s.setTcpNoDelay(true);
s.setKeepAlive(true);
new TcpConnectionHandler(s,this.packetHandler);
及
有时,即使有传入的数据包,TCP读取调用也会被长时间阻止
将编写一个测试Java客户端,以确定这不是由于Java中的行为造成的。
isConnected()
在测试时不可能为false。这不是对对等断开连接的测试,但是read()
返回的-1是,您忽略了它。@EJB,谢谢。这有助于我正确地关闭连接。我相信这对您有所帮助,但您的问题代码中没有反映这一点。“无限期过期”是什么意思?客户端向服务器发送了一个数据包。服务器上的Wireshark显示正在发送回客户端的ack。但尚未收到答复。在调试模式下,我知道read调用从未返回。如果我在命令提示符下按Ctrl+C,则读取返回,并且正在处理数据包。我在Ubuntu 16.04上运行了另一个服务器实例,到目前为止我还没有遇到任何问题。我的要求是它应该在Windows系统中运行。谢谢你的输入。我知道不需要每次都创建缓冲区。但主要问题仍然存在。我的数据包的最大大小限制为200字节,因此到目前为止2k足以处理。正如我已经提到的,我使用teraterm使用TCP协议连接到我的服务器。还有,在随机的时间里,我得到了这个区块。我想这里的键是终端中的Ctrl+C。当我中断终端时,数据包会得到服务。@Raavanan上面的代码应该做你想做的事情,在这种情况下,我会编写一个java客户端来证明这一点。我不知道你们的终端程序是否有异常。问题不在于终端,我已经用终端检查了其他案例。无论如何,我想操作系统也会带来一些不同。请查看更新。