使用多线程的基本套接字聊天程序引发错误

时间:2016-03-07 04:51:36

标签: python multithreading sockets networking

我正在使用套接字和多线程制作基本的聊天程序。程序已连接,当客户端发送消息时,它会在执行时在服务器端引发此错误:

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

我是初学者,也是多线程和套接字的新手。我做错了什么?

以下是我的客户代码:

#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

服务器代码:

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

完整代码可在此处找到:https://drive.google.com/folderview?id=0B3t3mUQs3K-iLWY3Y3JZX2YzU2c&usp=sharing

谢谢你:)

2 个答案:

答案 0 :(得分:1)

启动线程后,您的代码将关闭服务器和客户端代码中的远程套接字。在关闭它之前,你需要等待线程完成。

因此,对于服务器,删除最后一行c.close()。您可以使用t.join()在主线程中等待子线程。之后你可以关闭套接字。

您还可以更改线程代码,以便在远程客户端关闭套接字时终止。最好将套接字传递给线程,而不是让线程访问全局变量:

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

答案 1 :(得分:0)

这可能是因为您在已关闭的套接字上调用s.connect()。您可以在客户端代码中找到(在您附加的链接中找到),在s.connect((host, port))语句中执行while,这会导致您稍后在s.close语句中出现问题相同的代码。要解决此问题,您需要在s = socket.socket()语句之前将while命令移动到s.connect((host, port))语句中;这将确保s.connect((host, port))语句不会在已关闭的套接字上执行。