2

これは私が試したことです:

サーバ:

import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class JavaApplication12 {
    public static void main(String[] args) throws Exception{
    Charset charset = Charset.forName("ISO-8859-1");
    ServerSocketChannel s = ServerSocketChannel.open();
    s.configureBlocking(true);
    s.socket().bind(new InetSocketAddress(1024));
    CharBuffer c = CharBuffer.wrap("Hello from server!");
    System.out.println("writing " + c);
    ByteBuffer b = charset.encode(c);
    SocketChannel sc = s.accept();
    sc.configureBlocking(true);
    b.flip();
    int a = sc.write(b);
    sc.close();
    s.close();
    System.out.println("wrote " + a);
}
}

クライアント:

import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class JavaApplication11 {

    public static void main(String[] args) throws Exception {
    Charset charset = Charset.forName("ISO-8859-1");
    SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
    sc.configureBlocking(true);
    ByteBuffer b = ByteBuffer.allocate(32);
    b.flip();
    int a = sc.read(b);
    sc.close();
    b.flip();
    CharBuffer c = charset.decode(b);
    c.flip();
    System.out.println("Got " + c);
    System.out.println("read " + a );
}
}

反対側は非常に長く空の文字列を取得しているようで、何が間違っているのかわかりません。

更新: コードを更新したところ、サーバーが 0 バイトを書き込んでいることがわかりました。書き込むバイトがあるのに、何も書き込まないのはなぜsc.write()ですか?

更新 2 : Vishal の助けを借りて、最終的に実用的なソリューションが得られました。

サーバ:

Charset charset = Charset.forName("ISO-8859-1");
ServerSocketChannel s = ServerSocketChannel.open();
s.configureBlocking(true);
s.socket().bind(new InetSocketAddress(1024));
CharBuffer c = CharBuffer.wrap("Hello from server!");
ByteBuffer b = charset.encode(c);
SocketChannel sc = s.accept();
sc.configureBlocking(true);
b.compact();
b.flip();
int a = sc.write(b);
sc.close();
s.close();
System.out.println("wrote " + a);

クライアント:

Charset charset = Charset.forName("ISO-8859-1");
SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
sc.configureBlocking(true);
ByteBuffer b = ByteBuffer.allocate(32);
int a = sc.read(b);
sc.close();
b.flip();
CharBuffer c = charset.decode(b);
System.out.println("Got " + c);
4

2 に答える 2

3

Buffer.flip()メソッドは、Buffer を書き込みモードから読み取りモードに切り替えます。呼び出しflip()位置を 0 に戻し、制限を位置があった場所に設定します。
つまり、位置は読み取り位置をマークし、制限 はバッファに書き込まれたバイト数、文字数などをマークします-読み取ることができるバイト数、文字数などの制限

ドキュメントに次のBuffer.flip()ように記載されている場合:

一連のチャネル読み取りまたはput操作の後、このメソッドを呼び出して、一連のチャネル書き込みまたは相対取得操作の準備をします。

さらに、次のように述べています。

compactこの方法は、ある場所から別の場所にデータを転送するときに、この方法と組み合わせて使用​​されることがよくあります。

あなたの場合、put操作はByteBuffer 作成に使用されません。したがってcompact、フリップが呼び出される前にメソッドを呼び出す必要があります。

ByteBuffer's compact()メソッドは次のようになります。

バッファーの現在の位置とその制限の間にバイトがある場合は、バッファーの先頭にコピーされます。つまり、インデックス p = position() のバイトはインデックス 0 にコピーされ、インデックス p + 1 のバイトはインデックス 1 にコピーされ、インデックス limit() - 1 のバイトがインデックス n = にコピーされるまで同様に繰り返されます。 limit() - 1 - p。バッファーの位置は n+1 に設定され、その制限はその容量に設定されます。マークが定義されている場合、そのマークは破棄されます。

バッファーの位置は、0 ではなく、コピーされたバイト数に設定されるため、このメソッドの呼び出しの直後に、別の相対 put メソッドの呼び出しを行うことができます。 書き込みが不完全な場合に備えて、バッファからデータを書き込んだ後にこのメソッドを呼び出します。

サーバー側のコードでは、 Beforeflip()が呼び出され、位置自体が 0 でした。したがって、positionに書き込まれたバイト数を に設定するには、 が呼び出される前に メソッドbを呼び出して、 が に書き込まれたバイト数である前の値に設定し、 を に設定する必要があります。compact()b.flip()b.flip()limitpositionByteBufferposition0

したがって、サーバーコードは次のようになります。

import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class JavaApplication12 {
    public static void main(String[] args) throws Exception{
    Charset charset = Charset.forName("ISO-8859-1");
    ServerSocketChannel s = ServerSocketChannel.open();
    s.configureBlocking(true);
    s.socket().bind(new InetSocketAddress(1024));

    CharBuffer c = CharBuffer.wrap("Hello from server!");
    System.out.println("writing " + c);
    ByteBuffer b = charset.encode(c);
    System.out.println(new String(b.array()));
    SocketChannel sc = s.accept();
    //sc.configureBlocking(true);
    b.compact();
    System.out.println(b.capacity() + " "+ b.position() + " " + b.limit());
    b.flip();
    System.out.println(b.capacity() + " "+ b.position() + " " + b.limit());
    int a = 0;
    while (b.hasRemaining())
    {
        a += sc.write(b);
    }

    sc.close();
    s.close();
    System.out.println("wrote " + a);
    }
} 

同様に、クライアント側では、コードは次のようになります。

import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class JavaApplication11 {
    public static void main(String[] args) throws Exception {
    Charset charset = Charset.forName("ISO-8859-1");
    SocketChannel sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 1024));
    sc.configureBlocking(true);
    ByteBuffer b = ByteBuffer.allocate(32);
    //b.flip();//Don't flip the ByteBuffer here because it sets the position to 0 and limit to 0 also. Hence no read.
    int a = sc.read(b);
    sc.close();
    b.flip();//sets the Position to 0 and limit to the number of bytes to be read.
    CharBuffer c = charset.decode(b);
    //c.flip();//Don't flip the ChharBuffer. Because it is setting the position to zero and limit to previous position i.e zero
    System.out.println("Got " + c);
    System.out.println("read " + a );
    }
}

:間違いを犯した行にコメントを付けました。

于 2013-02-25T20:39:25.520 に答える
0

read()とdecode()の間でバッファをflip()する必要があります。

于 2013-02-25T22:08:18.977 に答える