与多个玩家的测验游戏,服务器没有从客户端接收信息

时间:2017-05-23 11:58:42

标签: python python-2.7 network-programming python-multithreading recv

我想用多人游戏编写一个问答游戏。 服务器部分选择问题,然后将其发送给客户端。客户端应答并将此答案发送到服务器。然后服务器检查它是否正确。我想循环这样做。 但问题是,存在时间问题,有时我的客户在能够回答之前没有收到问题。 另一个问题是,当客户端发送它时,服务器没有收到答案,我真的不知道原因。

这是我第一次进行网络编程,而且我很难理解线程和所有这些。 谢谢你的帮助=)

PS:这与另一个问题有关,我希望这段代码可以使用简单的图形界面......但这是下一步;)

这是我的客户代码:

import socket
import threading
import time

tLock = threading.Lock()
shutdown = False

def receving(name, sock):
    while not shutdown:
            try:
                tLock.acquire()
                while True:
                        data,addr = sock.recvfrom(1024)
                        print(str(data))
            except:
                    pass
            finally:
                    tLock.release()

#host = '192.168.26.86'
host = '127.0.0.1'
port = 0 #pick any free port currently on the computer
server = (host, 5000)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.setblocking(0)

#receiving thread
rT = threading.Thread(target=receving, args=("RecvThread", s))
rT.start()

alias = raw_input("Name: ")

#PLAYER ENTERS DATA
message = raw_input(alias + "First msg ->")

while message != 'q':
        tLock.acquire()
        message = raw_input(alias + "What is your answer ?  ->")
        tLock.release()


        if message != '':
            s.sendto(alias + ": " + message, server)

        time.sleep(0.2)

shutdown = True
rT.join()
s.close()

这是我的服务器代码:

import numpy as np
from numpy.random import shuffle
from random import randint
import socket
import time

#LIST OF QUESTIONS AND ANSWERS
question2 = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"]
answer2 = [["Paris","London","Berlin","Madrid"],
        ["South America","Africa","Europe","Asia"],
        ["London","New York","Mexico","Jakarta"],
        ["China","India","USA","Indonesia"],
        ["Portuguese","Spanish","French","English"]]
question_done=[0]*(len(question2))


#SCORE, stored as a list score[0]--> score of the player 1
score=[0]


#SHOW THE POSSIBLE ANSWERS
def displayA(question,answer,i):
    a = answer[i]
    order = np.arange(4)
    shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order
    a_display = [[a[order[0]],a[order[1]]],[a[order[2]],a[order[3]]]]
    print(a_display)


#CHOOSE RANDOMLY A QUESTION IN THE LIST
def chooseQuestion(question,answer):
    k = randint(0,len(question)-1)
    if (question_done[k]!=0):
        while(question_done[k]!=0):
            k = randint(0,len(question)-1)
        question_done[k]=1
    else :
        question_done[k]=1
    print(question[k])
    #displayA(question,answer,k)
    return k


#CHECK IF GOOD ANSWER OR NOT
def checkAnswer(answer,agiven,qnb):
    print("CHECK")
    test = False
    if(answer[qnb][0] in agiven):
        test = True
        score[0]=score[0]+1
    print("ANSWER")
    return test



#END OF GAME, DISPLAY OF SCORES
def final_score(score):
    print("The scores are {}".format(score))

    maxi = max(score)
    if(score.count(maxi)==1):
        print("The winner is Player {}".format(score.index(max(score))+1))
    else :
        winners = []
        for i in range(len(score)):
            if(score[i]==maxi):
                winners.append(i+1)
        print("The winners are players {}".format(winners))


"""

#Number of choosen questions, random order : GIVE THE QUESTION TO THE PLAYER
nb = 3

for k in range(nb):
   nbq = chooseQuestion(question2,answer2)
   agiven = raw_input("What is your answer?  ")
   result = checkAnswer(answer2,agiven,nbq)
   print("Your answer is {}".format(result))



#Say who the winner is
final_score(score)



"""
#START THE NETWORK CODE
#host = '192.168.26.86'
host = '127.0.0.1'

port = 5000

#list for all the players
players = []

#creation of socket object UDP and bind
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
#socket non blocking --> will always try to grab datas from the stream
#not block it
s.setblocking(0)


quitting = False
print "Server Started."

#NUMBER OF QUESTIONS
nb = 3


while (not quitting and nb>0):
    try:
            data, addr = s.recvfrom(1024)
            print("FIRST RECV {}".format(data))
            if "Quit" in str(data):
                quitting = True
            if addr not in players:
                players.append(addr)
                print("liste players {}".format(players))
                s.sendto("the game is starting ",players[len(players)-1])

            print time.ctime(time.time()) +  ":" + str(data)

            #GAME

            #for k in range(nb):
            print("question nb {}".format(nb))
            nbq = chooseQuestion(question2,answer2)


            for i in range(len(players)):
                print("ENTER FOR")
                #s.sendto(question2[nbq], players[i])
                try:
                    s.sendto(question2[nbq], players[i])
                    print("BEFORE GET ANSWER")
                    agiven, addr = s.recvfrom(1024)
                    print("GOT ANSWER")

                    print("agiven is : {}".format(agiven))
                    checkAnswer(answer2,agiven,nbq)

                    if "Quit" in str(agiven):
                        quitting = True
                    if addr not in players:
                        s.sendto("You cannot enter the game now ",addr)
                    else:
                        players[i] = addr
                except:
                    pass

            nb=nb-1

    except:
            pass



for i in range(len(players)):
    try:
        s.sendto("The game is finished, write q to quit",players[i])

    except:
        pass

final_score(score)
s.close()

1 个答案:

答案 0 :(得分:0)

您的代码包含正确的问题和答案逻辑,但客户端和服务器之间的数据传输非常脆弱,只有在时机完美时才能正常工作。

我修改了你的代码以帮助控制时间,并阻止事情失序。我使用select()系统调用来处理超时,在客户端我更改了读取线程,以便在问题从服务器到达时通知主循环。

这段代码距离完美还有很长的路要走但它确实有用,它应该可以帮助你构建一些按照你喜欢的方式工作的最终代码。

注意我删除了"你现在无法加入游戏"代码,以帮助我调试原始代码,所以你可能现在可以把它。希望这有用。

客户代码:

import socket
import threading
import time

tEv = threading.Event()
tShutdown = threading.Event()

def receving(name, sock):
    shutdown = False
    while not shutdown:
        try:
            data,addr = sock.recvfrom(1024)
            print(str(data))
            if '?' in data:
                tEv.set()
            if data == "The game is finished":  # message from server to stop
                tShutdown.set()
                shutdown = True
        except:
            pass
        finally:
            pass

#host = '192.168.26.86'
host = '127.0.0.1'
port = 0 #pick any free port currently on the computer
server = (host, 5000)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.setblocking(0)

# Start listener
rT = threading.Thread(target=receving, args=("RecvThread", s))
rT.start()

# Join the game
alias = raw_input("Name: ")
s.sendto(alias, server)

running = True
while running:
    if tEv.wait(1.0):
        tEv.clear()
        message = raw_input(alias + ", what is your answer ?  -> ")
        if message != '':
            s.sendto(alias + ": " + message, server)
    if tShutdown.is_set():
        running = False

rT.join()
s.close()

服务器代码:

import numpy as np
from numpy.random import shuffle
from random import randint
import socket
import time
import select

#LIST OF QUESTIONS AND ANSWERS
question2 = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"]
answer2 = [["Paris","London","Berlin","Madrid"],
        ["South America","Africa","Europe","Asia"],
        ["London","New York","Mexico","Jakarta"],
        ["China","India","USA","Indonesia"],
        ["Portuguese","Spanish","French","English"]]
question_done=[0]*(len(question2))


#SCORE, stored as a list score[0]--> score of the player 1
score=[0]


#SHOW THE POSSIBLE ANSWERS
def displayA(question,answer,i):
    a = answer[i]
    order = np.arange(4)
    shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order
    a_display = [[a[order[0]],a[order[1]]],[a[order[2]],a[order[3]]]]
    print(a_display)


#CHOOSE RANDOMLY A QUESTION IN THE LIST
def chooseQuestion(question,answer):
    k = randint(0,len(question)-1)
    if (question_done[k]!=0):
        while(question_done[k]!=0):
            k = randint(0,len(question)-1)
        question_done[k]=1
    else :
        question_done[k]=1
    print(question[k])
    #displayA(question,answer,k)
    return k


#CHECK IF GOOD ANSWER OR NOT
def checkAnswer(answer,agiven,qnb):
    #print("CHECK")
    test = False
    if(answer[qnb][0] in agiven):
        test = True
        score[0]=score[0]+1
    #print("ANSWER")
    return test



#END OF GAME, DISPLAY OF SCORES
def final_score(score):
    print("The scores are {}".format(score))

    maxi = max(score)
    if(score.count(maxi)==1):
        print("The winner is Player {}".format(score.index(max(score))+1))
    else :
        winners = []
        for i in range(len(score)):
            if(score[i]==maxi):
                winners.append(i+1)
        print("The winners are players {}".format(winners))


"""
#Number of choosen questions, random order : GIVE THE QUESTION TO THE PLAYER
nb = 3

for k in range(nb):
   nbq = chooseQuestion(question2,answer2)
   agiven = raw_input("What is your answer?  ")
   result = checkAnswer(answer2,agiven,nbq)
   print("Your answer is {}".format(result))

#Say who the winner is
final_score(score)
"""
#START THE NETWORK CODE
#host = '192.168.26.86'
host = '127.0.0.1'

port = 5000

#list for all the players
players = []

#creation of socket object UDP and bind
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
#socket non blocking --> will always try to grab datas from the stream
#not block it
s.setblocking(0)

print "Server Started."

#INITIAL SETUP PERIOD
secs = 20
max_players = 5

# WAIT FOR PLAYERS TO JOIN
while ((secs > 0) and (len(players) < max_players)):
    ready = select.select([s], [], [], 1)
    if ready[0]:
        data, addr = s.recvfrom(1024)
        print("FIRST RECV {}".format(data))
        if addr not in players:
            players.append(addr)
            print("liste players {}".format(players))
            s.sendto("Wait for game to start... ",players[len(players)-1])
        print time.ctime(time.time()) +  ":" + str(data)
    secs = secs - 1

#START GAME
print("Game starting")
for i in range(len(players)):
    try:
        s.sendto("Game starting", players[i])
    except:
        pass

#ASK QUESTIONS
nb = 3
for k in range(nb):
    print("question nb {}".format(k))
    nbq = chooseQuestion(question2,answer2)
    #print("ENTER FOR")
    for i in range(len(players)):
        try:
            s.sendto(str(question2[nbq]), players[i])
            #print("BEFORE GET ANSWER")
            agiven = ""
            ready = select.select([s], [], [], 10)
            if ready[0]:
                agiven, addr = s.recvfrom(1024)
                #print("GOT ANSWER")
            print("agiven is : {}".format(agiven))
            checkAnswer(answer2,agiven,nbq)
        except:
            pass

for i in range(len(players)):
    try:
        s.sendto("The game is finished", players[i])
    except:
        pass

final_score(score)
s.close()