首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AsynchronousSocketChannel一次写入/读取所有消息

AsynchronousSocketChannel一次写入/读取所有消息
EN

Stack Overflow用户
提问于 2014-04-24 21:24:03
回答 3查看 3.3K关注 0票数 0

尊重,

我尝试使用新的Java在客户端和服务器端创建异步SocketChannel并进行通信,但问题是我发送到socket的所有消息都在服务器上,socket读取所有消息作为一条消息。下面是代码:

我创建用于写入和读取数据的处理程序:

ReadHandler:

代码语言:javascript
复制
public class ReadHandler implements CompletionHandler<Integer, Msg> {


private AsynchronousSocketChannel _socket;
private SocketHandler _socketHandler;

private ByteBuffer _buffer;

public ReadHandler(SocketHandler socketHandler) {

    this._socketHandler = socketHandler;
    _buffer = ByteBuffer.allocate(100);

    this._socket = this._socketHandler.getSocket();
    this._socket.read(_buffer, null, this);
}

@Override
public void completed(Integer result, Msg attachment) {

    System.out.println("readdddd " + result);

    String message = new String(_buffer.array());
    System.out.println("mess:" + message);

}

@Override
public void failed(Throwable exc, Msg attachment) {
    System.out.println(exc.getMessage());
}

}

ClientWriteHandler

代码语言:javascript
复制
public class ClientWriteHandler implements CompletionHandler<Integer, Msg> {

private AsynchronousSocketChannel _socket;
private ClientSocket _clientHandler;

private ByteBuffer _buffer;

public ClientWriteHandler(ClientSocket clientHandler) {


    this._clientHandler = clientHandler;
    _buffer = ByteBuffer.allocate(2048);
    this._socket = this._clientHandler.getSocket();
}

@Override
public void completed(Integer result, Msg attachment) {

    System.out.println("write " + result);
    _buffer.clear();
}

@Override
public void failed(Throwable exc, Msg attachment) {
    System.out.println(exc.getMessage());
}

public void write(String data) {
    _buffer = ByteBuffer.allocate(2048);
    this._socket.write(_buffer.wrap(data.getBytes()), new Msg(), this);

}

}

然后我调用write方法2次

代码语言:javascript
复制
socket = AsynchronousSocketChannel.open();
        socket.connect(new InetSocketAddress("localhost", port)).get();
        writeHandler = new ClientWriteHandler(this);
        writeHandler.write("hellooo server :)");
        writeHandler.write("hellooo server again :)");

我尝试在ByteBuffer上使用clear()函数,但没有效果。有什么建议吗?

EN

回答 3

Stack Overflow用户

发布于 2014-09-11 21:03:16

引发WritePendingException不是因为缓冲区已满。它被抛出是因为写入未完成,但另一个开始写入。

票数 2
EN

Stack Overflow用户

发布于 2014-04-24 21:34:47

在第一个.write()调用中发送了几个字节,在第二个.write()调用中发送了几个字节。并且服务器接收所有它们。TCP是面向字节的。如果你想要消息之类的东西,你必须自己分隔你发送的消息,例如用特殊的换行符或XML标签。

票数 0
EN

Stack Overflow用户

发布于 2014-04-25 04:46:40

我在这上面工作,我找到了解决方案,就像我想象的那样。

在ClientWrite处理程序中,我添加了数据列表,并在try..catch中设置了write方法,以检查write()是否已完成,如果写入仍在进行中,则将新字符串添加到数据列表中。当write方法完成时,我检查数据列表中是否有新的消息,并再次写入消息。

代码语言:javascript
复制
public class ClientWriteHandler implements CompletionHandler<Integer, ByteBuffer> {

private AsynchronousSocketChannel _socket;
private ClientSocket _clientHandler;

private ByteBuffer _buffer;
private List<String> datas;

private boolean finished;

public ClientWriteHandler(ClientSocket clientHandler) {


    this._clientHandler = clientHandler;
    _buffer = ByteBuffer.allocate(2048);
    this._socket = this._clientHandler.getSocket();
    finished = true;
    datas = new ArrayList<>();
}

@Override
public void completed(Integer result, ByteBuffer attachment) {

    System.out.println("client write complete " + result);

    if(datas.size() > 0) {
        this._socket.write(_buffer.wrap(datas.remove(0).getBytes()), _buffer, this);
    }
    else {
        /////
    }
}

@Override
public void failed(Throwable exc, ByteBuffer attachment) {
    System.out.println(exc.getMessage());
}

public void write(String data) {

    try {
        //finished = false;
        this._socket.write(_buffer.wrap(data.getBytes()), _buffer, this);
    }catch(WritePendingException ex) {

        datas.add(data);
    }
}

}

此外,我在附件中发送缓冲区。在ReadHandler中,当读取完成时,我清除ByteBuffer并再次调用read()方法,所以下一次读取时,我得到了新的行,现在我不需要设置行分隔符。

代码语言:javascript
复制
public class ReadHandler implements CompletionHandler<Integer, ByteBuffer> {


private AsynchronousSocketChannel _socket;
private SocketHandler _socketHandler;

private ByteBuffer _buffer;

public ReadHandler(SocketHandler socketHandler) {

    this._socketHandler = socketHandler;
    _buffer = ByteBuffer.allocate(2048);

    this._socket = this._socketHandler.getSocket();
    this._socket.read(_buffer, _buffer, this);
}

@Override
public void completed(Integer result, ByteBuffer attachment) {

    attachment.flip();
    System.out.println("readdddd " + result);

    String message = new String(attachment.array());
    System.out.println("mess:" + message);

    _buffer.clear();
    this._socket.read(_buffer, _buffer, this);

}

@Override
public void failed(Throwable exc, ByteBuffer attachment) {
    System.out.println(exc.getMessage());
}

}

就目前而言,这很好用,但我将检查当我继续处理更复杂的东西时,这段代码将如何运行。你觉得这个解决方案可以吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23270240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档