Java 异步socketchannel一次写入/读取所有消息

Java 异步socketchannel一次写入/读取所有消息,java,sockets,asyncsocket,bytebuffer,Java,Sockets,Asyncsocket,Bytebuffer,尊重, 我尝试使用新的JavaNIO2在客户端和服务器端创建异步SocketChannel并进行通信,但问题是,我发送到服务器上socket的所有消息,socket都作为一条消息读取。以下是代码: 我创建用于写入和读取数据的处理程序: ReadHandler: public class ReadHandler implements CompletionHandler<Integer, Msg> { private AsynchronousSocketChannel _socket

尊重,

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

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

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

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

在第一个.write()调用中发送几个字节,在第二个.write()调用中再发送几个字节。服务器会接收所有的数据。TCP是面向字节的。如果您想要类似于消息的内容,则必须自行分离发送的消息,例如通过特殊的换行符或XML标记。

我对此进行了研究,并找到了解决方案,其效果与我想象的一样

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

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);
    }
}
公共类ClientWriteHandler实现CompletionHandler{
专用异步socketchannel\u套接字;
私人客户端套接字_clientHandler;
专用ByteBuffer缓冲区;
私有列表数据;
私有布尔完成;
公共客户端WriteHandler(客户端套接字客户端Handler){
这个._clientHandler=clientHandler;
_buffer=ByteBuffer.allocate(2048);
this.\u socket=this.\u clientHandler.getSocket();
完成=正确;
datas=newarraylist();
}
@凌驾
已完成公共作废(整数结果,ByteBuffer附件){
System.out.println(“客户端写入完成”+结果);
如果(datas.size()>0){
this.\u socket.write(\u buffer.wrap(datas.remove(0.getBytes()),\u buffer,this);
}
否则{
/////
}
}
@凌驾
公共作废失败(可丢弃的exc、ByteBuffer附件){
System.out.println(exc.getMessage());
}
公共无效写入(字符串数据){
试一试{
//完成=错误;
this.\u socket.write(\u buffer.wrap(data.getBytes()),\u buffer,this);
}捕获(WritePendingException-ex){
添加(数据);
}
}
}

我也在附件中发送缓冲区。 在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());
}
公共类ReadHandler实现CompletionHandler{
专用异步socketchannel\u套接字;
私人SocketHandler(U SocketHandler);
专用ByteBuffer缓冲区;
公共读处理器(SocketHandler SocketHandler){
这个._socketHandler=socketHandler;
_buffer=ByteBuffer.allocate(2048);
this.\u socket=this.\u socketHandler.getSocket();
this.\u socket.read(\u buffer,\u buffer,this);
}
@凌驾
已完成公共作废(整数结果,ByteBuffer附件){
附件.flip();
System.out.println(“readdddd”+结果);
字符串消息=新字符串(attachment.array());
System.out.println(“mess:+消息”);
_buffer.clear();
this.\u socket.read(\u buffer,\u buffer,this);
}
@凌驾
公共作废失败(可丢弃的exc、ByteBuffer附件){
System.out.println(exc.getMessage());
}
}


目前,这工作得非常好,但我将检查当我继续处理更复杂的东西时,这段代码的行为。您认为此解决方案可以吗?

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

OK但如果我的ByteBuffer已满,该怎么办?我尝试清除ByteBuffer,但在线程“main”java.nio.channels.WritePendingException中收到错误消息Exception
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);
    }
}
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());
}