Java SocketChannel write()返回时没有错误,但没有实际发送数据
我正在使用SocketChannel与远程服务器通信。我使用socketChannel.write()发送数据,没有错误和异常,但是,服务器日志表明没有收到任何数据;客户端tcp流量监视器还显示ByteBuffer中的字符串消息未发送 谁能给我一个提示为什么会这样?谢谢大家!Java SocketChannel write()返回时没有错误,但没有实际发送数据,java,sockets,nio,socketchannel,Java,Sockets,Nio,Socketchannel,我正在使用SocketChannel与远程服务器通信。我使用socketChannel.write()发送数据,没有错误和异常,但是,服务器日志表明没有收到任何数据;客户端tcp流量监视器还显示ByteBuffer中的字符串消息未发送 谁能给我一个提示为什么会这样?谢谢大家! public class Client implements Runnable { SocketChannel socketChannel; Selector selector; Selection
public class Client implements Runnable {
SocketChannel socketChannel;
Selector selector;
SelectionKey key;
ByteBuffer inbuf, outbuf;
int id;
@Override
public void run() {
try {
// prepare inbuf and outbuf
inbuf = ByteBuffer.allocate(10000);
outbuf = ByteBuffer.allocate(10000);
// prepare a socket channel for communication
socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("<remote server ip>", ));
selector = Selector.open();
socketChannel.configureBlocking(false);
key = socketChannel.register(selector, SelectionKey.OP_READ
| SelectionKey.OP_WRITE);
while (selector.select() > 0) {
if (key.isReadable()) {
// read from channel when server sends data
read();
}
if (key.isWritable()) {
// write
Random r = new Random(500);
write("b", r.nextInt(), r.nextInt());
for (int i = 0; i < 10; i++) {
// write a message to server after 1 second
Thread.sleep(1000);
write("m", r.nextInt(), r.nextInt());
}
write("e", r.nextInt(), r.nextInt());
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void write(String action, int x, int y) throws IOException {
String msg = String.format("%s:%d:%d:%d", action, id, x, y);
int r=outbuf.remaining();
outbuf.put(msg.getBytes());
int rBytes = outbuf.remaining();
boolean connected = socketChannel.isConnected();
Socket sock = socketChannel.socket();
if (connected && sock.isConnected() && !sock.isOutputShutdown())
>>>>>>>>>> socketChannel.write(outbuf);
else
System.out.println("Connection broken!");
System.out.printf("Client %d told server:%s\n", id, msg);
//outbuf.clear();
}
... //read omitted here
公共类客户端实现可运行{
SocketChannel SocketChannel;
选择器;
选择键;
ByteBuffer inbuf,Exputf;
int-id;
@凌驾
公开募捐{
试一试{
//准备inbuf和extuf
inbuf=字节缓冲分配(10000);
exputf=字节缓冲分配(10000);
//为通信准备一个套接字通道
socketChannel=socketChannel.open();
连接(新的InetSocketAddress(“,”);
选择器=selector.open();
socketChannel.configureBlocking(假);
key=socketChannel.register(选择器,SelectionKey.OP_读取
|选择键。操作(写入);
while(selector.select()>0){
if(key.isReadable()){
//服务器发送数据时从通道读取数据
read();
}
if(key.isWritable()){
//写
随机r=新随机数(500);
写(“b”,r.nextInt(),r.nextInt());
对于(int i=0;i<10;i++){
//在1秒后将消息写入服务器
睡眠(1000);
写(“m”,r.nextInt(),r.nextInt());
}
写(“e”,r.nextInt(),r.nextInt());
}
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
私有void write(字符串操作,int x,int y)引发IOException{
String msg=String.format(“%s:%d:%d:%d”,操作,id,x,y);
int r=exputf.remaining();
put(msg.getBytes());
int rBytes=exputf.remaining();
布尔连接=socketChannel.isConnected();
Socket sock=socketChannel.Socket();
if(已连接&&sock.isConnected()&&sock.isOutputShutdown())
>>>>>>>>>>socketChannel.write(extuf);
其他的
System.out.println(“连接中断!”);
System.out.printf(“客户端%d告诉服务器:%s\n”,id,msg);
//exputf.clear();
}
…//此处省略
将内容放入缓冲区或将内容读入缓冲区后,必须翻转缓冲区才能写入或从中获取数据。请检查Buffer类中的flip()
方法。文档中说
翻转此缓冲区。将限制设置为当前位置,然后将该位置设置为零。如果定义了标记,则将其丢弃。
在一系列通道读取或put操作之后,调用此方法以准备一系列通道写入或相对get操作
因此,在put之后添加buffer.flip()应该可以做到这一点:)在将内容放入缓冲区或将内容读入缓冲区后,您必须翻转缓冲区以写入或从中获取数据。检查buffer类中的
flip()
方法。文档说
翻转此缓冲区。将限制设置为当前位置,然后将该位置设置为零。如果定义了标记,则将其丢弃。
在一系列通道读取或put操作之后,调用此方法以准备一系列通道写入或相对get操作
因此,在put之后添加一个buffer.flip()应该可以做到这一点:)您是否翻转了ByteBuffer?编辑:不,您没有……我正在写答案。谢谢!Hi@EJP,你能看一下我问的另一个问题吗?谢谢。你翻了吗编辑:不,你没有……我正在写答案。谢谢!Hi@EJP,你能看一下我问的另一个问题吗?谢谢你。+1并且不要忽略
write()返回的值.
在这种情况下它应该是零,这应该会触发警钟。谢谢@xp500,它可以工作!我确实读到ByteBuffer或Buffer类通常可以在读和写模式之间“翻转”。既然可以工作,这是否意味着我在ByteBuffer中“放入”一些字节后,SocketChannel write()方法将实际读取缓冲区并通过套接字的outputStream写入它?Thanks@EJP,谢谢你的提示!@user798637检查文档中的buffer类。它定义了3个属性:limit、position和capacity。我假设write方法以某种方式迭代缓冲区(可能使用haslaining()方法)然后将其写入流。这就是你要问的吗?@xp500,是的,谢谢。如果你不介意我在这里问另一个相关问题,而不启动新线程,那么这里就是:现在在“翻转”缓冲区后,流量监视器指示我的数据已发送,但服务器似乎确实收到了,因为我的服务器具有非常简单的逻辑,而呃,它得到了一些东西,它只是将它回显到所有其他连接的客户端(广播),我用nc命令测试了我的服务器,它正常工作。所以我想知道这里还有什么问题。+1并且不要忽略write()返回的值.
在这种情况下它应该是零,这应该会触发警钟。谢谢@xp500,它可以工作!我确实读到ByteBuffer或Buffer类通常可以在读和写模式之间“翻转”。既然可以工作,这是否意味着我在ByteBuffer中“放入”一些字节后,SocketChannel write()方法将实际读取缓冲区并通过套接字的outputStream写入它?Thanks@EJP,谢谢你的提示!@user798637检查文档中的buffer类。它定义了3个属性:limit、position和capacity。我假设write方法以某种方式迭代缓冲区(可能是