为什么客户端无法从服务器接收消息(java)

时间:2012-10-15 04:13:56

标签: java multithreading client nio

我刚刚开始学习java。我修改了服务器/客户端通信程序的客户端代码,为客户端创建了两个线程,用于接收用户输入的主线程,以及用于接收服务器响应的inputThread。我确信服务器已将响应发送到客户端,但是,客户端没有获得响应消息。

这是我的代码。任何人都可以帮我搞清楚吗?感谢

package clientnio;

import java.net.*; 
import java.nio.*; 
import java.io.*;
import java.nio.channels.*; 
import java.util.Scanner; 

public class ClientNIO {
public static int bufferLen = 50;
public static SocketChannel client;
public static ByteBuffer writeBuffer;
public static ByteBuffer readBuffer;

public static void main(String[] args) { 
    writeBuffer = ByteBuffer.allocate(bufferLen);
    readBuffer = ByteBuffer.allocate(bufferLen);

    try { 
        SocketAddress address = new InetSocketAddress("localhost",5505); 
        System.out.println("Local address: "+ address);
        client=SocketChannel.open(address);
        client.configureBlocking(false); 

        //readBuffer.flip();
        new inputThread(readBuffer);

        /*
        String a="asdasdasdasddffasfas"; 
        writeBuffer.put(a.getBytes()); 
        writeBuffer.clear();  
        int d=client.write(writeBuffer);
        writeBuffer.flip();
        */

        while (true) {
            InputStream inStream = System.in;
            Scanner scan = new Scanner(inStream);
            if (scan.hasNext()==true) {
                String inputLine = scan.nextLine();
                writeBuffer.put(inputLine.getBytes()); 
                //writeBuffer.clear();
                System.out.println(writeBuffer.remaining());
                client.write(writeBuffer);
                System.out.println("Sending data: "+new String(writeBuffer.array()));
                writeBuffer.flip(); 
                Thread.sleep(300);
            }
        }                 
    } 
    catch(Exception e) { 
        System.out.println(e);
    } 

}
}

class inputThread extends Thread {
private ByteBuffer readBuffer;
public inputThread(ByteBuffer readBuffer1) {  
    System.out.println("Receiving thread starts.");
    this.readBuffer = readBuffer1;
    start();
}

@Override
public void run() {
    try {
        while (true) {
            readBuffer.flip();
            int i=ClientNIO.client.read(readBuffer); 
            if(i>0) { 
                byte[] b=readBuffer.array(); 
                System.out.println("Receiving data: "+new String(b)); 
                    //client.close(); 
                    //System.out.println("Connection closed."); 
                    //break; 
            }
            Thread.sleep(100); 
        }
    }
    catch (Exception e) {
       System.out.println(e);
    }
  }
}

2 个答案:

答案 0 :(得分:1)

在读取之前在缓冲区上调用flip()是错误的。不要那样做。您需要在+写入+之前将其翻转,或从中获取,然后再compact()

答案 1 :(得分:-1)

免责声明:我不是Java的活跃用户。 (我只在学校使用它。)


建议:如果您使用阻止模式,我认为这将大大简化调试过程,至少在您的代码示例正常工作之前。 (目前您的代码似乎没有受益于非阻塞模式。)


我发现了两个问题,最终导致可能需要更改的四行代码:

  1. ByteBuffer分配其后备阵列时,它通过将position设置为零并将limit设置为该阵列的容量来设置自己准备写入。你对ByteBuffer.flip()的两种用法(分别在写循环和阅读循环中)似乎与惯例相悖。
  2. 调用ByteBuffer.array()方法始终返回整个后备数组,因此它的大小始终为bufferLen。因此,从全尺寸数组构造的String可能包含来自先前传输的垃圾。
    • 通常,需要将数组修剪为传输大小,并且String和字节数组之间的转换必须使用与服务器相同的编码。

  3. 我对第一期的建议更改:
    (注意:我不知道如何修复数组修剪和编码问题。)

    writeBuffer.put(inputLine.getBytes()); 
    writeBuffer.flip();                       // <--here
    client.write(writeBuffer);
    ...
    writeBuffer.clear();                      // <-- should be clear() instead of flip()
    Thread.sleep(300);
    

    // readBuffer.flip();                      // <-- remove this line
    int i=ClientNIO.client.read(readBuffer); 
    if(i>0) { 
        readBuffer.flip();                     // <-- move it here
        byte[] b=readBuffer.array(); 
        System.out.println("Receiving data: "+new String(b)); 
        ...
    }
    

    参考