我只是想知道是否可以使用SocketChannel类(使用ByteBuffer)来模拟Java中常规Socket类的阻塞功能。我制作了两个测试项目,一个模拟客户端,另一个模拟服务器:
客户代码:
public static void main(String[] args) throws IOException {
SocketChannel socket = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6789));
//Simulate this:
//DataOutputStream dos = new DataOutputStream(socket.socket().getOutputStream());
//dos.writeInt(4);
//dos.writeInt(6);
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(4);
buffer.flip();
socket.write(buffer);
buffer.clear();
buffer.putInt(6);
buffer.flip();
socket.write(buffer);
}
服务器代码:
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(6789));
SocketChannel socketCh = ssc.accept();
socketCh.configureBlocking(true);
// Simulate this
// DataInputStream dis = new DataInputStream(socketCh.socket().getInputStream());
// System.out.println(dis.readInt());
// System.out.println(dis.readInt());
// This is something to avoid. This is not the same as what is up above
// If the 2nd line prints -1, the 3rd prints 4
// If the 2nd line prints 4, the 3rd prints 6
ByteBuffer buffer = ByteBuffer.allocate(1024);
socketCh.read(buffer);
buffer.rewind();
System.out.println("First number: " + buffer.getInt());
buffer.clear();
System.out.println("Change: " + socketCh.read(buffer));
buffer.rewind();
System.out.println("Second Number: " + buffer.getInt());
}
正如我在评论中所说,运行服务器然后客户端(按此顺序)的结果是不可预测的,因为有时第二个数字可能保持为4或变为6,其中更改为-1或4(字节)在整数)。
至于服务器端,我知道我可以让它等待,以便第二个socketCh.read(缓冲区)返回一个非-1的值,这意味着在SocketChannel中没有写入(我推测)。
然而,在客户端,我没有任何想法。
我知道我可以使用DataOutputStream和DataInputStream来做旧方式,但我想知道如何使用SocketChannels来简化方便。另外,你可以通过另一种技巧来解决问题。
即使我手动将服务器配置为阻止,我也认为它是默认配置,因此可以将其丢弃。
提前谢谢! PS:希望我能避免使用Selector类来完成这么简单的任务......
编辑:我知道Selector类只能用于非阻塞模式。
答案 0 :(得分:1)
您丢弃了可能已读取的额外数据,并假设每次读取都准确地传达了与每次写入相对应的内容(例如,第一次只传送int
)。 TCP中没有任何内容可以保证这一点。
将rewind()
更改为flip()
;将clear()
更改为compact()
;添加一些read()
的返回值检查;它应该按预期工作。
您无法在阻止模式下使用Selector
。