0

私はJavaを学び始めたばかりです。サーバー/クライアント通信プログラムのクライアント側コードを変更しました。クライアント側には、ユーザーの入力を受信するためのメインスレッドと、サーバーの応答を受信するためのinputThreadの2つのスレッドを作成しました。サーバーがクライアントに応答を送信したことは確かですが、クライアントで応答メッセージが取得されません。

これが私のコードです。誰かが私がそれを理解するのを手伝ってくれる?ありがとう

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

2 に答える 2

0

flip()読み取る前にバッファを呼び出すのは間違っています。そうしないでください。あなたはそれから書く前に、またはそれから得る前に、そしてcompact()その後それをひっくり返す必要があります。

于 2012-10-15T08:57:47.793 に答える
0

免責事項:私はJavaのアクティブユーザーではありません。(私は学校でのみ使用しました。)


アドバイス:少なくともコード例が正しく機能するまでは、ブロッキングモードを使用すると、デバッグプロセスが大幅に簡素化されると思います。(現在、コードは非ブロッキングモードの恩恵を受けていないようです。)


私は2つの問題を特定し、変更が必要になる可能性のある4行のコードに至りました。

  1. がバッキングアレイを割り当てると、ゼロとそのアレイの容量にByteBuffer設定することで、書き込みの準備が整います。(それぞれ書き込みループと読み取りループでの)2つの使用法は、規則に反しているようです。positionlimitByteBuffer.flip()
  2. メソッドを呼び出すと、ByteBuffer.array()常にバッキング配列全体が返されるため、サイズは常にになりますbufferLen。このためString、フルサイズのアレイから構築されたものには、以前の送信からのジャンクが含まれている可能性があります。
    • 通常、配列は送信サイズに合わせて調整する必要があり、aStringとバイト配列間の変換ではサーバーと同じエンコーディングを使用する必要があります。

最初の問題に対して提案された変更:(
注:配列のトリミングとエンコードの問題を修正する方法がわかりません。)

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

参考文献

于 2012-10-15T04:36:05.600 に答える