koush / AndroidAsync

Asynchronous socket, http(s) (client+server) and websocket library for android. Based on nio, not threads.
Other
7.51k stars 1.56k forks source link

client got Connection reset by peer error when try to send binary message #716

Open chenzx opened 1 year ago

chenzx commented 1 year ago

Server side code:

public class AsyncMessageReceiver extends Thread implements AsyncHttpServer.WebSocketRequestCallback {
    static final String TAG = "BRTC/AsyncMessageReceiver";
    int listenPort;
    AsyncHttpServer asyncHttpServer;
    List<WebSocket> sockets = new ArrayList<>();
    Map<String, WebSocket> id2sockets = new HashMap<>();
    MessageListener listener;

    @Override
    public void onConnected(WebSocket webSocket, AsyncHttpServerRequest request) {
        sockets.add(webSocket);
        //WebSocket is only a interface, no getId() method, so cast to Object then get a hashcode as client connection id;
        final String id = ""+((Object)webSocket).hashCode();
        id2sockets.put(id, webSocket);
        webSocket.setDataCallback(new DataCallback() {
            @Override
            public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                byte[] data = bb.getAllByteArray();
                Log.d(TAG, "onDataAvailable: data="+AsyncMessageUtils.ByteArray2String(data));
                if(AsyncMessageReceiver.this.listener!=null){
                    AsyncMessageReceiver.this.listener.onBinaryMessage(data);
                }
            }
        });
        webSocket.setClosedCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception e) {
                try {
                    if (e != null)
                        Log.e(TAG, e.getMessage(), e);
                } finally {
                    sockets.remove(webSocket);
                    id2sockets.remove(id);
                }
            }
        });
    }

    interface MessageListener {
        void onBinaryMessage(byte[] msg);
    }

    public AsyncMessageReceiver(int port){
        Log.d(TAG, "ctor: port="+port);
        this.listenPort = port;
        asyncHttpServer = new AsyncHttpServer();
        asyncHttpServer.websocket("/msg", this);
    }

    public void run(){
        Log.d(TAG, "run: enter");
        asyncHttpServer.listen(AsyncServer.getDefault(), this.listenPort); //how to stop?
    }

    public void setMessageListener(MessageListener listener){
        this.listener = listener;
    }
}

Client:

public class AsyncMessageSender implements AsyncHttpClient.WebSocketConnectCallback {
    static final String TAG = "BRTC/AsyncMessageSender";
    public final static int MAX_MTU_LIMIT = 1450;

    private String url;
    private AsyncHttpClient asyncHttpClient;
    private WebSocket webSocket;

    public AsyncMessageSender(String host, int port){
        url = "http://"+host+":"+port+"/msg";
        asyncHttpClient = AsyncHttpClient.getDefaultInstance();
        Log.i(TAG, "ctor: connect to "+url);
        asyncHttpClient.websocket(url, (String)null, (AsyncHttpClient.WebSocketConnectCallback) this);
    }

    public void emit(byte[] msg){
        if(msg.length>MAX_MTU_LIMIT){
            throw new RuntimeException("msg size "+msg.length+" over MAX_MTU_LIMIT!");
        }
        Log.d(TAG, "emit: send msg="+AsyncMessageUtils.ByteArray2String(msg));
        this.webSocket.send(msg);
    }

    @Override
    public void onCompleted(Exception ex, WebSocket webSocket) {
        if(ex!=null){
            Log.e(TAG, "onCompleted: ERROR "+ex.getMessage(), ex);
            throw new RuntimeException("Cannot connect to "+url);
        }
        Log.d(TAG, "onCompleted: connected to "+this.url);
        this.webSocket = webSocket; //TODO: reconnect when temp connect error?
        //no setDataCallback since client is send-only;
    }

    public void close(){
        Log.d(TAG, "close");
        this.webSocket.close();
    }
}

Error:

E/NIO: Unhandled exception
    java.io.IOException: Connection reset by peer
        at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
        at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
        at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
        at sun.nio.ch.IOUtil.read(IOUtil.java:197)
        at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:421)
        at com.koushikdutta.async.SocketChannelWrapper.read(SocketChannelWrapper.java:30)
        at com.koushikdutta.async.AsyncNetworkSocket.onReadable(AsyncNetworkSocket.java:134)
        at com.koushikdutta.async.AsyncServer.runLoop(AsyncServer.java:878)
        at com.koushikdutta.async.AsyncServer.run(AsyncServer.java:726)
        at com.koushikdutta.async.AsyncServer.access$800(AsyncServer.java:46)
        at com.koushikdutta.async.AsyncServer$8.run(AsyncServer.java:680)

I have not seen emit log, so the client first try to read something when connected to server?

chenzx commented 1 year ago

I use 2 servers & 2 clients associated with 2 different ports (url), is it the client's connected to server then "Connection reset by peer"'s reason?

chenzx commented 1 year ago

Try to convert byte[] to Base64 String, then no "Connection reset by error" But client sends 20~30 messages in a short time, server side only receives 1?