J.Clarke
J.Clarke

Reputation: 370

Basic Socket Chat Program Using Multithreading Raises Errors

I am making a basic chat program using socket and multi threading. The program connected and when a message is sent from the client it raises this error on the server side when executed:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
    self.run()
  File "C:\Python27\lib\threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "C:\Users\jclarke14\Desktop\Server - 2.py", line 25, in check_for_data
    data = c.recv(1024)
  File "C:\Python27\lib\socket.py", line 174, in _dummy
    raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor

I am a beginner and new to multi-threading and socket. What am i doing wrong?

Here is my code for the Client:

#Check For Incoming Data

def check_for_data():
    while True:
        data = s.recv(1024)
        print "Other: " + data
        print

#Send Data

def send_data():
    while True:
        message = raw_input("You: ")
        print
        s.sendall(message)

#Start Threads 
t = threading.Thread(target=send_data)
t.daemon = True
t.start() #1

t = threading.Thread(target=check_for_data)
t.daemon = True
t.start() #2

And Code for Server:

c, addr = s.accept()

print "Connection From: " + str(addr)
print

def check_for_data():
    while True:
        data = c.recv(1024)
        print "Other: " + str(data)
        print

def send_data():
    while True:
        message = raw_input("You: ")
        print
        c.sendall(message)

#Start Threads 
t = threading.Thread(target=send_data)
t.daemon = True
t.start() #1

t = threading.Thread(target=check_for_data)
t.daemon = True
t.start() #2

The Full code is available Here: https://drive.google.com/folderview?id=0B3t3mUQs3K-iLWY3Y3JZX2YzU2c&usp=sharing

Thank You :)

Upvotes: 1

Views: 90

Answers (2)

mhawke
mhawke

Reputation: 87074

After starting the thread your code closes the remote socket in both the server and client code. You need to wait for the thread to complete before closing it's socket.

So, for the server remove the last line c.close(). You can wait in the main thread for the child thread using t.join(). After that you can close the socket.

You could also change your thread code so that it terminates when the remote client closes the socket. And it is better to pass the socket to the thread than it is to have the thread access a global variable:

def check_for_data(c):
    while True:
        data = c.recv(1024)
        if data:
            print "Other: " + str(data)
        else:
            print "Client closed connection"
            c.close()
            break

t = threading.Thread(target=check_for_data, args=(c,))
t.daemon = True
t.start()

t.join()
#c.close()    # if you don't close it in the thread
s.close()    # close the main server socket

Upvotes: 1

bbkglb
bbkglb

Reputation: 769

It's probably because you're calling s.connect() on a socket that has already been closed. You see how in your client code (found on the link you attached), you are doing s.connect((host, port)) inside the while statement, that is causing the problem with the s.close statement you have later in the same code. To fix that you need to move the s = socket.socket() command into your while statement before the s.connect((host, port)) statement; that would ensure that the s.connect((host, port)) statement will not be executed on a closed socket.

Upvotes: 0

Related Questions