高手解贴!----从未遇到过的Socket通讯怪问题!

java_dd 2005-10-11 07:26:09
状况:
两台机通过Socket通讯,服务端每秒发送一心跳信号(4byte标志位+4byte包长度位+16byte全部0xaa),客户端通过下面的程序接收并解包。
问题:
程序运行后前15次能够正常接收到心跳信号的数据并能正确解包,但第16次开始就不能接收到数据,程序中的iLength值为-1,以后都不能接收到数据。请问这是为什么?
部分代码:

/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: www.gdie.com</p>
*
* @author java_dd@yahoo.com.cn
* @version 1.0
*/
public class SocketReceiveFromCP extends Thread {
private static Logger log = Logger.getLogger(SocketReceiveFromCP.class);
static Socket server;
public boolean bStop = false;

/**
* 从车牌接收数据
*/
public void run() {
try {
server = new Socket(InetAddress.getByAddress(Business.getIpv4("CPIP")), 33002);
DataInputStream in = new DataInputStream(server.getInputStream());
// BufferedInputStream in = new BufferedInputStream(server.getInputStream());
// BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
// BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream(), "ISO8859-1"));
// String str = "";
int iPackageFlag = 0x55aa55aa;
int iheart = 0;

while (true) {
byte[] bSmallBuf = new byte[16];
//取前面8个字节
int iLength = in.read(bSmallBuf, 0, 8);
String sTemp = new String(bSmallBuf);
log.info("包:" + sTemp + "--------iLength:" + iLength );
if (iLength < 8) {
continue;
}
//取数据包起始标志
int iRead = getPackageFlag(bSmallBuf);
//如果是包起始
if (iRead == iPackageFlag) {
//得到包长度
int iPackageLength = getPackageLength(bSmallBuf);
if (iPackageLength == 16) { //如果是心跳信号
in.read(bSmallBuf, 0, 16);
log.info("心跳" + iheart++);
continue;
}
//是车牌数据包信号
byte[] bBuf = new byte[4194304];
int iReadLength = iPackageLength;
//读完整个数据包的所有数据
while (iReadLength > 0) {
int iThisReadLength = in.read(bBuf, 0, iReadLength);
iReadLength -= iThisReadLength;
}


}
}
}
}
}
...全文
200 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wintangtang 2005-10-14
  • 打赏
  • 举报
回复
byte[] bSmallBuf = new byte[16];
是这句话的数组越界了吧
zgysc 2005-10-14
  • 打赏
  • 举报
回复
up!
java_dd 2005-10-14
  • 打赏
  • 举报
回复
问题解决了,正如taolei所言,服务器端会关闭了连接。非常感谢taolei!
原因是这样的:服务器不但是每秒给我发心跳信号,而且需要我回应心跳信号,15秒收不到我的回应就认为我这边的连接已经断开,它则关闭当前连接,重新启一个连接。如此循环。
但这些供应商的文档却没有说,真不厚道。
多谢各位!
taolei 2005-10-13
  • 打赏
  • 举报
回复
InputStream.read如果返回-1,表示Stream已经被对方关闭了(closed by peer)。你要查一查为什么服务器端会关闭这个Stream或连接。
believefym 2005-10-13
  • 打赏
  • 举报
回复
帮顶。。。
java_dd 2005-10-13
  • 打赏
  • 举报
回复
java_dd 2005-10-13
  • 打赏
  • 举报
回复
taolei,非常感谢你给我的帮助!

我按你的把in.read改成in.readFully,但问题还是一样。发生问题时(后)服务端的Socket并没有死,再次尝试连接仍能接收到15次心跳数据。我用我自己编写的服务端又不会有问题。供应商的服务端用C写的,运行在Linux,我测试的服务端是用JAVA写的,运行在Windows2000。

你第二次回贴可能是因为我没清除掉已注释的代码,代码简洁后其实是这样的:
public void run() {
try {
server = new Socket(InetAddress.getByAddress(Business.getIpv4("CPIP")), 33002);
DataInputStream in = new DataInputStream(server.getInputStream());
int iPackageFlag = 0x55aa55aa;
int iheart = 0;

while (true) {
byte[] bSmallBuf = new byte[16];
//取前面8个字节
int iLength = in.read(bSmallBuf, 0, 8);
if (iLength < 8) {
continue;
}



}
}
}
taolei 2005-10-11
  • 打赏
  • 举报
回复
你的程序还有些问题,socket的InputStream只能用一次。尤其是你后面用了BufferedInputStream和BufferedReader,这些类是有缓冲的,它们一次读取一整块数据。例如,其第一次需要4个byte的数据,但bufferedInputStream一次可能读了512个字节的数据,后面的数据就只用通过这个类才能读到,而其他的通过socket的getInputStream的InputStream就读不到后面的数据了。
taolei 2005-10-11
  • 打赏
  • 举报
回复
把in.read改成in.readFully

in.read不能保证一次读到你所需要的长度的数据包。通常用DataInputStream的readFully以及readInt等函数来读取数据,这些函数会一直读到所需要长度的数据后(或出错)才会返回。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧