Python 使用线程时出现套接字问题

Python 使用线程时出现套接字问题,python,multithreading,sockets,Python,Multithreading,Sockets,我在业余时间一直在做一个python游戏,我遇到了一个问题。我使用基本线程模块处理套接字,当我使用一个客户端连接到服务器文件时,它工作正常。但除此之外,任何在第一次冻结服务器和第一个客户机之后连接的服务器都会被冻结 这是服务器的代码 import socket import random import thread from saveState import Save from grid import Grid import time players = 0 save = Save() g

我在业余时间一直在做一个python游戏,我遇到了一个问题。我使用基本线程模块处理套接字,当我使用一个客户端连接到服务器文件时,它工作正常。但除此之外,任何在第一次冻结服务器和第一个客户机之后连接的服务器都会被冻结

这是服务器的代码

import socket
import random
import thread
from saveState import Save
from grid import Grid   
import time
players = 0
save = Save()
grid = Grid()

def ready(c):
    ready = raw_input("Are you ready to play?\n")
    if(ready == "yes" or ready == "y"):
        grid.makeGrid() 
        c.send("ready")
def clientThread(conn,players):

    while True:
        print "taking requests"
        request = conn.recv(1024)
        segments = request.split(",,")
        if(segments[0] == "0" and players<200):
            print "registering player", addr
            serial = random.choice(list(range(999999)))
            conn.send("{}".format(serial))
            save.players[serial] = segments[2:]
            print save.players[serial][9]
            players+=1
        elif(segments[0] == "3"):
            if(segments[2] == "land"):
                conn.send("{},,{},,{},,{}".format(grid.getLandType(int(save.players[serial][9]),int(save.players[serial][10])), grid.getDesc(int(save.players[serial][9]),int(save.players[serial][10])),int(save.players[serial][9]),int(save.players[serial][10])))
        elif(segments[0]=="2"):
            if(segments[2]=="playerX" and int(segments[3])==-1):
                save.players[serial][9] = int(save.players[int(serial)][9])-1 
            elif(segments[2]=="playerX"):
                save.players[serial][9] = int(save.players[int(serial)][9])+1 
            if(segments[2]=="playerY" and int(segments[3])==-1):
                save.players[serial][10] = int(save.players[int(serial)][10])-1 
            elif(segments[2]=="playerY"):
                save.players[serial][10] = int(save.players[int(serial)][10])+1 
        elif(segments[0]=="4"):
            alreadySent = []
            for m in grid.monsters:
                if(m.X==save.players[int[segment[1]]][9] and m.Y==save.players[int[segment[1]]][10] and alreadySent[m]==False):
                    conn.send("{},,{}".format(m.name, True))
                elif(time.clock == 60*60*(12+8)):
                    conn.send("{},,{}".format("You see the sun set on the horizon. Monsters will be more aggressive now.", False))
        else:       
            print "sorry, there is an inconsistency in the request or the queue is full."



try:
    #start up socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    name = socket.gethostbyname(socket.gethostname())
    print name
    port = input("select port\n")
    s.bind((name, port))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    #listen for any attempts to connect to the api
    #if anyone connects, give them a serial number and add their data to a storage file
    while True: 
        s.listen(5)
        c,addr = s.accept()
        thread.start_new_thread(ready,(c,))
        thread.start_new_thread(clientThread,(c, players))
    conn.close
    sock.close
except socket.error:
    print " either the server port is closed or in use. try again"
导入套接字
随机输入
导入线程
从保存状态导入保存
从网格导入网格
导入时间
玩家=0
save=save()
grid=grid()
def就绪(c):
就绪=原始输入(“准备好播放了吗?\n”)
如果(就绪==“是”或就绪==“y”):
grid.makeGrid()
c、 发送(“准备就绪”)
def客户端线程(康涅狄格州,玩家):
尽管如此:
打印“接受请求”
请求=conn.recv(1024)
段=请求。拆分(“,”)
如果(段[0]=“0”和播放器0):
s、 发送(“{},,{},,{},,{}.”格式(2,串行,“playerX”,-1))
睡眠时间(0.5)
elif(action==“east”和player.locX0):
s、 发送(“{},{},{},{},{},{}”。格式(2,序列号,“playerY”,-1))
睡眠时间(0.5)

elif(action==“south”和player.locY所以问题在于控制台输入,正如SmallNothing所说的那样。如果没有严重的黑客攻击,就没有办法绕过这个限制,所以我建议即兴创作。我的解决方案是用python创建一个web应用程序,而不是使用控制台。这有一些好处

  • 服务器可以一次轻松处理多个输入
  • 输入时可能会发生问题(我的问题的解决方案)
  • 用户无需下载任何文件,因为只需输入网址即可访问所有内容
虽然不是一个完美的解决方案,但有时找到替代方案是次好的选择


谢谢大家的帮助!

我不知道答案,但是你应该使用
线程
模块,而不是
线程
,它是一个更高级的界面。要回答你的问题,s.listen(5)在安装时不应该被调用多次,将其移出while循环。只有s.accept()应该为每个客户端调用。
conn.recv
可以读取部分消息,而您的代码会中断。@在问题开始之前,几乎没有任何东西是我从while循环中获取的。只是为了检查,我再次将其移出,问题仍然存在。还有,Daniel,您所说的部分消息是什么意思。我没有收到任何错误,everything只是停止有趣的是,我刚刚测试了它,这就是导致我的程序完全按照您描述的方式停止的原因。不幸的是,我可以看到程序中有一些错误,但下一个最有可能的错误是ready函数中的raw_输入,因为许多控制台应用程序的工作方式raw_输入将阻塞所有线程,直到某些输入因此,您不应该将其作为线程。
import random
from grid import Grid
from player import Player
from descriptions import Descriptions
import socket
import time
import thread
description = Descriptions()

def descisionHandler(s,serial):
    while True:
        s.send("{},,{},,{}".format(3,serial,"land"))
        response = s.recv(1024).split(",,")
        print "you are on a {} tile \n {} \n {} \n {}".format(response[0], response[1],response[2], response[3])
        action=raw_input("What Will You Do?\n")
        try:
            if(action == "west" and player.locX>0):
                s.send("{},,{},,{},,{}".format(2,serial,"playerX",-1))
                time.sleep(0.5)
            elif(action == "east" and player.locX<199):
                s.send("{},,{},,{},,{}".format(2,serial,"playerX",1))
                time.sleep(0.5)
            elif(action == "north" and player.locY>0):
                s.send("{},,{},,{},,{}".format(2,serial,"playerY",-1))
                time.sleep(0.5)
            elif(action == "south" and player.locY<199):
                s.send("{},,{},,{},,{}".format(2,serial,"playerY",1))
                time.sleep(0.5)
          #  elif(action == "attack" and monster_data[1]):
              #  print "The {} wakes up! A battle begins!".format(monster_data[0])
            elif(action == "profile"):
                print " You are {} \n  {} \n your role is {} \n you have an attack of {} \n a defense of {} \n a speed of {} \n and {} hitpoints \n attacks: {} \n you are located at  {} {}".format(player.name,
                    player.backstory,player.role,player.attack,player.defense,player.speed, player.hitpoints, player.attacks, player.locX, player.locY)
            elif(action == "exit"):
                break
        except IndexError:
            pass

def eventHandler(s,serial):
    while True:
        s.send("{},,{}".format(4,serial))
        response = s.recv(1024).split(",,")
        print response[0]
        return bool(response[1])



while True:
    try:
        print "\nWelcome to Overseer! We need a few things before we begin\n"
        name = raw_input("What is your name?\n")
        backstory = raw_input("What is in your past: choose one \n chosen \n magician \n poet\n")
        role = raw_input("what is your class: choose one \n Warrior \n Mage \n Rougue \n Bard\n")
        player = Player(name,description.player_backstory[backstory], role, 5,5,5,10, {"scrap": 10}, random.choice(list(range(200))), random.choice(list(range(200))))

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = raw_input("what host are you connecting to?")
        port = input("what port?\n")

        s.connect((host,port))
        print "connection successful." 
        time.sleep(5)
        s.send("{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{},,{}".format(0,0,name,backstory,role,5,5,5,5,10,player.attacks,player.locX,player.locY))
        serial = s.recv(1024)
        print "You're serial number is {}".format(serial)
        while(s.recv(1024) != "ready"):
            pass
        break
    except socket.error:
        print "server is not running or is busy. please try again."

eventThread = thread.start_new_thread(eventHandler,(s,serial))
descisionThread = thread.start_new_thread(descisionHandler,(s,serial))

while 1:
    pass