2017-05-14 54 views
0

我是新的Python和线程,所以请冷漠。我正在尝试在Python中做2人游戏。数据通过tcp/ip协议(客户端 - 服务器架构)发送。在服务器上我有三个线程。一个与一个用户交流,第二个与第二个和第三个线程交流,我得到的是由客户端发送的其他两个线程的数据。这些数据用于检查游戏是否结束。这一切都很好。问题从现在开始。当游戏结束时,我想发送另一个数据给客户端。所以线程3需要向客户端发送数据,但其他两个线程仍在工作,他们仍然与客户端有连接。通常我不知道如何做到这一点。我试图通过队列从第三个线程发送信息给他人,他们应该关闭他们的连接。它的线程类代码:线程和TCP/IP连接问题

class myThread(threading.Thread): 
    def __init__(self, threadID, name, conn, conn2, kto, wartosc, 
wybor,kolejkaZadan,gracz1,gracz2): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.name = name 
     self.conn = conn 
     self.conn2 = conn2 
     self.kto = kto 
     self.wartosc = wartosc 
     self.wybor = wybor 
     self.kolejkaZadan = kolejkaZadan 
     self.gracz1 = gracz1 
     self.gracz2 = gracz2 

     def run(self): 
      if self.wybor == None:  
      toClient(self.conn,self.conn2,self.kto,self.wartosc,self.gracz1) 
      else: 
       while True: 

       data,kolejkaZwrotna = self.kolejkaZadan.get() // I receive data from two others threads 
       time.sleep(10) 
       dataKolejne,kolejkaZwrotna = self.kolejkaZadan.get() // I receive data from two others threads 

       if data is dataKolejne: // if end 
        tworzenieXmla(self.gracz1, self.gracz2) 
        odczytywanieXmla('itemGracza1',gracz1Otrzymane) 

        plik = open('Marcin.xml', 'rb') 

        czyZamknacConnection = True 
        kolejkaZwrotna.put(czyZamknacConnection) // send data to two others threads 

        while True: 
         czescXmla = plik.read(10000) 

        #self.conn2.send(czescXmla) 

而且这是这是由其他两个线程执行我的发送/接收地功能:

def toClient(conn, conn2, kto, wartosc,gracz): 
wordsBackup = None 
kolejkaZwrotna = queue.Queue() 

while True: 

    data = conn.recv(BUFFER_SIZE) 

    if not data: 
     break 

    if kolejkaZwrotna.get() is True://receive form thread 3 
     conn2.close() 
     print('closed') 
     break 

    if len(data)>7: 
     print('WARNING', data) 

    words = str(data.decode()).split() 
    #print(words[0], words[1]) 

    if kto==1: 
     conn2.send(data) 


    if kto==2: 
     conn2.send(data) 

    kolejkaZadan.put(words[2],kolejkaZwrotna) // send to thread 3 
    xmlTablicaDoZapisu(str(int(words[0])),str(int(words[1])),str(int(words[2])),gracz) 

一般不存在错误,我们可以发挥,但只有一个球员在因此我认为每台计算机服务器都不会发送数据。我将不胜感激任何帮助。

回答

1

对于您当前的情况,修复方法是将所有连接变量更改为您可以迭代的连接的array。您可能想要构建一些定义其行为的容器类,因为并非所有客户端都是相同的(服务器客户端和播放器客户端)。这样你就不会受到你声明的变量数量和线程数量的限制。 然后,一旦有新的客户端连接你,只需将它添加到数组中,你的迭代器就会处理剩下的事情。

虽然这是TCP/IP的一个常见问题,因为您始终必须打开连接到n客户端,这不仅占用资源,而且由于TCP/IP是排队协议,它还可以设置整个游戏如果任何客户端连接速度较慢,则返回。在实践中,你的比赛总是和最糟糕的球员一样迟钝。

您有几个选项。

  1. 您可以让一个线程始终打开,它处理连接。你的supervisor线程。它包含一系列开放连接的数据并将操作分配给其他线程。这不是最好的选择,因为你很快就会遇到Race Conditions,比如两个线程试图使用相同的数据。
  2. 您可以切换到UDP,由于没有持续连接,这会使线程变得很开放。然后,您需要向每个客户端发送状态,一旦他们可以摆脱数据。大多数游戏现在都实现UDP,甚至是基于回合的。

Beej的指南可能是关于UDP/TCP和套接字控制理论的最广泛的互联网。 http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

而且还有Gaffer游戏,这也是一个很好的资源。 http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/