多人问答游戏,服务器不接收来自客户端的信息

Quiz Game with multi players, server doesn't receive information from clients

我想编写一个多人问答游戏。 服务器部分选择问题,然后将其发送给客户端。客户端回答并将此回答发送到服务器。服务器然后检查它是否正确。我想循环执行此操作。 但问题是,有一个时间问题,有时我的客户在能够回答之前没有收到问题。 另一个问题是,客户端发过来的时候服务器收不到,我也不知道为什么。

这是我第一次做网络编程,对我来说很难理解线程和所有这些。 谢谢你的帮助=)

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()

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

我已经修改了您的代码以帮助控制时间,并防止出现乱序。我使用 select() 系统调用来处理超时,并且在客户端中我更改了读取线程以在问题从服务器到达时通知主循环。

这段代码距离完美还有很长的路要走,但它确实有效,它应该可以帮助您构建最终以您喜欢的方式工作的东西。

注意我删除了 "you can't join the game now" 代码以帮助我调试原始代码,因此您现在可以将其放回原处。希望这对您有所帮助。

客户代码:

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()