多线程tcp服务器python

时间:2017-08-15 13:05:13

标签: python multithreading tcp

我正在尝试在python中创建一个多线程TCP服务器。 当接受新客户端时,它将转到新创建的线程。 但是,当早期客户端发送数据时,看起来新创建的线程会拦截它们,因此从服务器端看起来只有较新的客户端正在发言!

这是我的代码:

Nbre = 1

class ClientThread(threading.Thread):

   def __init__(self, channel, connection):
      global Nbre
      Nbre = Nbre + 1
      print("This is thread "+str(Nbre)+" speaking")
      self.channel = channel
      self.connection = connection
      threading.Thread.__init__(self)

   def run(self):
      print(connection[0]+':'+str(connection[1])+'<'+str(Nbre)'> Connected!')
      try:
         while True:
             data = self.channel.recv(1024)
             if data:
               print(connection[0]+':'+str(connection[1])+'<'+str(Nbre)+'> '+str(data.strip('\n')))
             else:
               break
      finally:
         print(connection[0]+':'+str(connection[1])+'<'+str(Nbre)+'> Exited!')
         self.channel.close()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('', 4747))
server.listen(0)
while True:
   channel, connection = server.accept()
   ClientThread(channel, connection).start()

这是我在推出时得到的,telnet客户端为第一个客户端发送“Hello”,第二个客户端发送“Bonjour”:

 $ python simple_thread.py 
This is thread 2 speaking  # new connection
127.0.0.1:33925> Connected!
127.0.0.1:33925<2> hello
This is thread 3 speaking  # new connection
127.0.0.1:33926> Connected!
127.0.0.1:33926<3> Bonjour # last connected says "Bonjour" (ok here)
127.0.0.1:33926<3> hello   # first connected re-send "hello" but in thread 3?!

为什么第二次发送“hello”没有从线程2中弹出?以及如何让它发生,以便我可以从服务器端回复到相应的客户端?

非常感谢! (线程新手:/)

1 个答案:

答案 0 :(得分:1)

好消息是,它可能有效,但您的日志记录已被破坏。在这里使用Nbre,这是线程数,而不是当前线程的数量:

           print(connection[0]+':'+str(connection[1])+'<'+str(Nbre)+'> '+str(data.strip('\n')))

因此,要使其工作,请将当前线程的编号存储在线程对象上,然后使用它。像这样:

   def __init__(self, channel, connection):
     global Nbre
     Nbre = Nbre + 1
     self.number = Nbre

connection对象存在类似问题。日志记录使用connection而不是self.connection。通常情况下,您会收到错误,但由于底部的while循环会创建一个全局connection变量,因此该变量会被拾取。因此,请在日志记录中使用self.connection

为了您自己的理智,我还建议将日志记录提取到一个函数中,然后使用string.format

def log(self, message):
   print('{}:{}<{}> {}'.format(self.connection[0], str(self.connection[1]), self.number, message)

因此,您只需编写self.log('Thread started'),而不是每次都重复日志格式。