Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connection reset by peer [errno 104] in Python 2.7

I've seen and read a lot about this particular issue on the internet. I am writing a simple chat server and client using socket in python for learning purpose mainly.

I've observed an issue here.

Here is my server code :

__author__ = 'pchakraverti'

import socket
import select
import sys


class NickSocketMap(object):
    count = 0

    def __init__(self, nick, client_socket):
        self.nick = nick
        self.client_socket = client_socket
        NickSocketMap.count += 1

    @staticmethod
    def display_count():
        print "Total number of clients is %d" % NickSocketMap.count


host = ""
port = 7575
socket_list = []
nick_list = []
cnt = 0
recv_buffer = 1024


def register_nick(nick, client_socket):
    obj = NickSocketMap(nick, client_socket)
    nick_list.append(obj)


def process_request(request_string, client_socket):
    parts = request_string.split("|")
    if parts[0] == "set_nick":
        register_nick(parts[1], client_socket)
        client_socket.send("nick_set")
    elif parts[0] == "transmit_msg":
        broadcast_message(parts[1], parts[2])
    return 1


def broadcast_message(message, client_nick):
    for s in nick_list:
        if s.nick == client_nick:
            try:
                s.client_socket.send(message)
            except socket.errno, ex:
                print ex
            break


def run_server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        sock.bind((host, port))
    except socket.errno, ex:
        print ex
        sys.exit(-1)
    sock.listen(10)
    # add the parent socket in the list
    socket_list.append(sock)
    # keep the server alive
    while True:
        try:
            read_ready, write_ready, in_error = select.select(socket_list, [], [], 0)
        except select.error, ex:
            print ex
            continue
        for s in read_ready:
            # check if s is the parent socket
            if s == sock:
                # accept new connection and append to list
                try:
                    con, addr = s.accept()
                    if con not in socket_list:
                        socket_list.append(con)
                except socket.errno, ex:
                    print ex
            else:
                try:
                    # receive packet from connected client
                    packet = s.recv(recv_buffer)
                    if not packet:
                        socket_list.remove(s)
                        read_ready.remove(s)
                        for n in nick_list:
                            if n.client_socket == s:
                                nick_list.remove(n)
                                break
                        break
                    print packet
                except socket.errno, ex:
                    print ex
                    continue
                process_request(packet, s)
    sock.close()


if __name__ == "__main__":
    run_server()

and here is my client code:

__author__ = 'pchakraverti'

import socket


nick = ""
host = "192.168.0.167"
port = 7575
sock = ""


def welcome():
    print "Welecome to SecuChat!"
    print "---------------------"


def init():
    nick = raw_input("Enter your chat nickname : ")
    print nick
    global sock
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        sock.connect((host, port))
    except socket.errno, ex:
        print ex
    sock.send("set_nick|"+nick)
    #sock.close()

if __name__ == "__main__":
    welcome()
    init()

In the client code, when I don't do the sock.close(), the server runs into an exception :

Traceback (most recent call last):
  File "server.py", line 102, in <module>
    run_server()
  File "server.py", line 84, in run_server
    packet = s.recv(recv_buffer)
socket.error: [Errno 104] Connection reset by peer

how ever, when I add that line, the problem doesn't occur.

Now I've two questions :

i) I've handled exceptions in the server.py, why is this exception not being handled and why is it crashing the code ? How can I make the server more robust and what am I missing ?

ii) What is the logic behind this crash and exception in relation to the sock.close() line in the client ?

like image 405
Priyabrata Avatar asked Dec 06 '22 20:12

Priyabrata


1 Answers

i) Your try-except block doesn't catch any exceptions.

The first argument to except must be the type of the exception you want to catch. socket.errno is not an exception class but a module. You need to catch socket.error:

 except socket.error, ex:
     print ex

It "crashes" your code because any exception that isn't handled somewhere in the call stack propagates outwards until it hits an except. If there is no handler the program is terminated.

ii) When the client terminates without closing the connection, a RST packet is sent by the TCP/IP stack of your OS. This is roughly the equivalent of hanging up a phone without saying goodbye. Python converts this into an exception with the text "Connection reset by peer". It simply means that since you called read() Python assumed you expect to receive something and when the connection suddenly disconnected, Python informs you of this by raising the exception.

like image 61
cg909 Avatar answered Dec 16 '22 01:12

cg909