状况:
    两台机通过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 [email protected]
 * @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;
}


}
}
}
}
}

解决方案 »

  1.   

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

  2.   

    你的程序还有些问题,socket的InputStream只能用一次。尤其是你后面用了BufferedInputStream和BufferedReader,这些类是有缓冲的,它们一次读取一整块数据。例如,其第一次需要4个byte的数据,但bufferedInputStream一次可能读了512个字节的数据,后面的数据就只用通过这个类才能读到,而其他的通过socket的getInputStream的InputStream就读不到后面的数据了。
      

  3.   

    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;
    }



    }
    }
    }
      

  4.   

    InputStream.read如果返回-1,表示Stream已经被对方关闭了(closed by peer)。你要查一查为什么服务器端会关闭这个Stream或连接。
      

  5.   

    byte[] bSmallBuf = new byte[16];
    是这句话的数组越界了吧
      

  6.   

    问题解决了,正如taolei所言,服务器端会关闭了连接。非常感谢taolei!
    原因是这样的:服务器不但是每秒给我发心跳信号,而且需要我回应心跳信号,15秒收不到我的回应就认为我这边的连接已经断开,它则关闭当前连接,重新启一个连接。如此循环。
    但这些供应商的文档却没有说,真不厚道。
    多谢各位!