这是我尝试过的:
服务器:
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);
答案 0 :(得分:3)
Buffer.flip() 方法切换缓冲区 模式到阅读模式。致电
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,其限制设置为其容量。标记,如果定义, 被丢弃了。
缓冲区的位置设置为复制的字节数 而不是为零,以便可以遵循此方法的调用 立即通过调用另一个相对put方法。 在写入不完整的情况下从缓冲区写入数据后调用此方法。
在服务器端的代码中调用flip()
之前,位置本身为0。因此,要将position
设置为写入b
的数字字节,您必须在调用compact()
之前调用b.flip()
方法,以便b.flip()
设置limit
1}}到前一个position
,这是写入ByteBuffer
的字节数,并将position
设置为0
。
因此,您的服务器代码应如下所示:
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);
}
}
LikeWise,在客户端,您的代码应该是这样的:
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 );
}
}
注意:我已对您犯错的行发表评论。