现有两个程序,Sender和Receiver,Sender不停制造数据包,通过Socket传给Receiver。节选代码如下:
Sender:    public void run() {
        try {
            Socket sock = new Socket("211.66.6.217", 10001);
            DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));
            int len = 58164;
            byte[] content = new byte[58164];
            for (int i = 0; i < len; i++) {
                content[i] = 1;
            }
            while(true) {
                dos.writeInt(len);
                dos.write(content);
                logger.debug("send bytes");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }    }Receiver:
    public void run() {
        try {
            ServerSocket serv = new ServerSocket(10001);
            System.out.println("Waiting for connection");
            Socket sock = serv.accept();
            while (true) {
                DataInputStream dataIn = new DataInputStream(new BufferedInputStream(sock
                        .getInputStream()));
                int len = dataIn.readInt();
                logger.debug("readLen = " + len);
                byte[] content = new byte[len];
                dataIn.read(content, 0, len);
                
            }        } catch (Exception e) {
            e.printStackTrace();
        }
    }在localhost上运行两个程序,没有问题。
但是在局域网内的两台机上运行,不久会出现发送的len和接收的len不相等的情况,而且接受的len可能是一个很大的负数,导致程序出错。
如果在Sender的循环里加入Thread.sleep(500),则可以无限期正常运行。
这是否说明,Java的Socket不能承受高负荷?

解决方案 »

  1.   

    DataInputStream dataIn = new DataInputStream(new BufferedInputStream(sock
                            .getInputStream()));
    不要放到循环体内,否则每次包装可能会buffer一些数据了
      

  2.   

    我把DataInputStream dataIn = new DataInputStream(new BufferedInputStream(sock
                            .getInputStream()));
    放到循环体外,不加Thread.sleep(500)len仍然会变得不一致。
    最奇怪的是,加了Thread.sleep(500)后,偶尔会有几次接收到的len变得很大,随后又恢复正常。
    按理,当接收到的len变得很大,dataIn.read(content, 0, len)会造成错位才对,为什么后面的一切正常??
      

  3.   

    int length = dataIn.read(content);
    注意检查length的长度,如果不够则循环
    length = dataIn.read(content,length);
      

  4.   

    还有,len只会变成一个数:16843009
    真是奇怪
      

  5.   

    to lxleaves(飘泊的叶子)我这是测试程序,原来的程序,接收方是不知道长度的。
      

  6.   

    可能是因为局域网内网速限制的问题,比如说是发送方的发送速度快于接受方的数据接受速度,这样就导致数据虽然在发送方发送了但是接受方却无法正常接受。不过仅仅在局域网内网速应该不成问题的呀?!可以用 lxleaves(飘泊的叶子)所提出的方法再看看,根据接受的数据长度来进行循环接受。。
      

  7.   

    DataInputStream类的 read(byte[] b, int off, int len)方法的文档是这样写的:Reads up to len bytes of data from the contained input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read, possibly zero. The number of bytes actually read is returned as an integer. 也就是说read()方法会尝试去读取len长度的字节,但是并不保证一定能一次就读到这么多字节。由于网络的延迟等因素,实际读取的字节数可能会比len少。这个方法会返回实际读到的字节数。
    在你的程序里的这一句 dataIn.read(content, 0, len); 很可能并没有读到len个字节,然后下一个循环中的这一句 int len = dataIn.readInt(); 实际上得到的是上一个循环里没有读完的 byte[] content = new byte[58164]; 中的内容。你说读到的len全都是 16843009, 这个数转换成二进制是 00000001 00000001 00000001 00000001, 不就正好是你发送的content的内容么。这一句 dataIn.read(content, 0, len); 应该改成
    int n = 0;
    do
    {
        n += dataIn.read(content, n, len - n);
    }
    while (n < len);