Dart ServerSocket Connection reset by peer

817 views
Skip to first unread message

azproduction

unread,
Oct 17, 2011, 11:09:17 AM10/17/11
to General Dart Discussion
I just created simple Dart http server and stat to ab it. ab often
ends with "apr_socket_recv: Connection reset by peer (54)" What is
wrong?
https://gist.github.com/1292557

Florin Malita

unread,
Oct 17, 2011, 2:26:00 PM10/17/11
to azproduction, General Dart Discussion
    void onConnect() {
        List<int> receiveBuffer = new List();

        Socket receiveSocket = serverSocket.accept();
        InputStream inputStream = receiveSocket.inputStream;
        OutputStream outputStream = receiveSocket.outputStream;

        inputStream.readUntil(receiveBuffer, bufferReady);
        outputStream.write(output, 0, output.length, onSend);

        receiveSocket.close();
    }

The main problem is that you're performing I/O and closing the socket in your onConnect() handler. The current Dart socket API is non-blocking => your read there is most likely not getting any data, and you're closing the connection before the peer has had a chance to send anything.

You should be waiting for receiveSocket events and perform the I/O only when notified. Also keep in mind that reads and writes can always transfer fewer bytes than requested. Try something like this:

    void onConnect() {
        void onWrite(Socket sock, int offset) {
            int written = sock.writeList(output, offset, output.length - offset);
            if (written > 0 && written < output.length - offset)
                sock.setWriteHandler(() => onWrite(sock, offset + written));
            else
                sock.close();
        }

        void onData(Socket sock) {
            List<int> buf = new List<int>(1024);
            // this is incomplete - should keep reading until a full HTTP request is received
            sock.readList(buf, 0, buf.length);
            sock.setWriteHandler(() => onWrite(sock, 0));
        }

        void onClose(Socket sock) {
            sock.close();
        }

        Socket receiveSocket = serverSocket.accept();
        receiveSocket.setCloseHandler(() => onClose(receiveSocket));
        receiveSocket.setDataHandler(() => onData(receiveSocket));
        
        return;
    }



azproduction

unread,
Oct 20, 2011, 5:01:15 AM10/20/11
to General Dart Discussion
I updated my script, but the problem is still there.

https://github.com/azproduction/dart-http/blob/master/HttpServer.dart#L190-199

On 18 окт, 00:26, Florin Malita <fmal...@google.com> wrote:

Florin Malita

unread,
Oct 20, 2011, 1:47:30 PM10/20/11
to azproduction, General Dart Discussion
On Thu, Oct 20, 2011 at 5:01 AM, azproduction <azazel....@gmail.com> wrote:
I updated my script, but the problem is still there.

https://github.com/azproduction/dart-http/blob/master/HttpServer.dart#L190-199


What level of concurrency are you using with AB (-c) and what OS are you running on?

I was able to consistently complete 100K runs @ 100 concurrent requests with the following tweaks:

* removed the onClose() handler - apparently the socket is cleaned up automatically; calling close explicitly in the handler is race-prone and can end up throwing an invalid socket exception
* increased listen backlog - this must be able to buffer the number of concurrent connections that AB throws at it before they're accepted.

FWIW, I could trigger the same AB errors running against Apache when I lowered its ListenBacklog setting to something like 10. It also seems to be a poor error message choice (connection reset by peer) because a packet capture showed it was really AB resetting the connection (while trying to close it after a connect timeout), and not its peer.

Try the patch below and let me know whether it stabilizes your runs - it did for me.

--
Florin


--- HttpServer.dart.orig 2011-10-20 10:17:27.359189967 -0400
+++ HttpServer.dart 2011-10-20 13:40:43.637947155 -0400
@@ -166,7 +166,7 @@
 
     HttpServer listen(cb(HttpRequest request, HttpResponse response)) {
         // initialize the server
-        serverSocket = new ServerSocket(host, port, 5);
+        serverSocket = new ServerSocket(host, port, 100);
         if (serverSocket == null) {
             throw "can't get server socket";
         }
@@ -198,13 +198,8 @@
         }
     }
 
-    void _onClose(Socket sock) {
-        sock.close();
-    }
-
     void _onConnect() {
         Socket receiveSocket = serverSocket.accept();
-        receiveSocket.setCloseHandler(() => this._onClose(receiveSocket));
         receiveSocket.setDataHandler(() => this._onData(receiveSocket));
         return;
     }

Reply all
Reply to author
Forward
0 new messages