简体   繁体   English

AsynchronousSocketChannel在一个中写入/读取所有消息

[英]AsynchronousSocketChannel write/read all messages in one

Respect, 尊重,

I try to use new Java NIO2 to create Asynchronous SocketChannel on the client and on the server side and communicate, but problem is that all messages I sent to socket on the server, socket read all as one message. 我尝试使用新的Java NIO2在客户端和服务器端创建异步SocketChannel并进行通信,但问题是我发送到服务器上的套接字的所有消息,套接字都作为一条消息读取。 here is code: 这是代码:

I create handlers for writing and reading data: 我创建了用于编写和读取数据的处理程序:

ReadHandler: ReadHandler:

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 ClientWriteHandler

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);

}

} }

Then I call write method 2 time 然后我叫写方法2次

socket = AsynchronousSocketChannel.open();
        socket.connect(new InetSocketAddress("localhost", port)).get();
        writeHandler = new ClientWriteHandler(this);
        writeHandler.write("hellooo server :)");
        writeHandler.write("hellooo server again :)");

I try to use clear() function on the ByteBuffer but no effect. 我尝试在ByteBuffer上使用clear()函数但没有效果。 Any suggestion? 有什么建议吗?

WritePendingException was thrown not because the buffer is full. 抛出WritePendingException不是因为缓冲区已满。 It is thrown because writing is not completed but another starts to write. 抛出它是因为写入没有完成但是另一个开始写入。

You send a few bytes in the first .write() call and send a few more bytes in the second call to .write(). 您在第一次.write()调用中发送几个字节,并在第二次调用中向.write()发送几个字节。 And the server receives them all. 并且服务器全部接收它们。 TCP is byte oriented. TCP是面向字节的。 If you want anything like a message, you have to seperate the messages you send on your own, eg by special line break characters or XML tags. 如果你想要一条消息,你必须单独发送你自己发送的消息,例如通过特殊的换行符或XML标签。

I work on this and I found solution and its work as I imagined. 我正在努力,我找到了解决方案和我想象的工作。

Inside of ClientWrite handler I added datas list and set write method inside try..catch to check if write() is finihed, if writing is still in process I add new string to datas list. 在ClientWrite处理程序内部我添加了数据列表并在try..catch中设置了write方法以检查write()是否已经完成,如果写入仍在进行中,我将新字符串添加到数据列表中。 When write method is finished I check datas list for new messages and write message again. 写入方法完成后,我检查数据列表中的新消息并再次写入消息。

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);
    }
}

} }

Also I send buffer in attachment. 我也在附件中发送缓冲区。 Inside ReadHandler when reading is complete I clear ByteBuffer and call read() method again, so next reading I got as new line, now I dont need to set line separator. 阅读完成后,在ReadHandler里面我清除ByteBuffer并再次调用read()方法,所以接下来读到我的新行,现在我不需要设置行分隔符。

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());
}

} }

For now this works so good, but i will check how this code will behave when I went on with more complex stuffs. 现在这个工作非常好,但是当我继续使用更复杂的东西时,我会检查这段代码的行为方式。 What do you think for this solution is it ok? 你觉得这个解决方案怎么样?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM