Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to reproduce "Connection reset by peer"

I have learned the differences between the two infamous errors in tcp:

  • [Errno 54] Connection reset by peer
  • [Errno 32] Broken pipe

Both errors are one side of the tcp connection closed for unknown reason, and the other side still communicate with it.

  • when the other side write something, Broken pipe is thrown
  • when the other side read something, Connection reset by peer is thrown

I was able to reproduce Broken pipe using Python codes below.

# tcp_server.py
def handler(client_sock, addr):
    try:
        print('new client from %s:%s' % addr)
    finally:
        client_sock.close()   # close current connection directly

if __name__ == '__main__':

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('', 5500))
    sock.listen(5)

    while 1:
        client_sock, addr = sock.accept()
        handler(client_sock, addr)

As for client,

>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.connect(('', 5500))
>>> sock.send('a')
1
>>> sock.send('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.error: [Errno 32] Broken pipe

When the client first send, a RST packet is sent from server to client, from this moment on, send will always throw Broken pipe.

Everything above is within my understanding. However when client read from server , it always return empty string instead of throw Connection reset by peer

>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.connect(('', 5500))
>>> sock.recv(1024)
''
>>> sock.recv(1024)
''
>>> sock.recv(1024)
''
>>> sock.recv(1024)

I am confused at this, or generally how to reproduce the Connection reset by peer ?

like image 831
Jiacai Liu Avatar asked Nov 24 '16 01:11

Jiacai Liu


1 Answers

You can set the socket "linger" option to 0 and close the socket to send a reset. Updating your server

import socket
import struct
import time

# tcp_server.py
def handler(client_sock, addr):
    try:
        print('new client from %s:%s' % addr)
        time.sleep(1)
    finally:
        client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
            struct.pack('ii', 1, 0))
        client_sock.close()   # close current connection directly

if __name__ == '__main__':

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', 5500))
    sock.listen(5)

    while 1:
        client_sock, addr = sock.accept()
        handler(client_sock, addr)

And running this client

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('', 5500))
print(sock.recv(1024))

I got

Traceback (most recent call last):
  File "tcpclient.py", line 5, in <module>
    print(sock.recv(1024))
ConnectionResetError: [Errno 104] Connection reset by peer
like image 132
tdelaney Avatar answered Sep 28 '22 08:09

tdelaney