我是python的新手。我曾多次尝试学习时遇到困难,但在查找错误报告后我终于可以搞清楚了。现在,经过8个小时试图解决这个问题后,我的想法就没了。
我正在尝试制作一个非常简单的联网(排序)游戏。客户端告诉服务器鼠标的位置。服务器将新客户端添加到其客户端列表中,并将客户端列表及其位置发送回客户端。之后,客户端将在屏幕上发送到圈子的值进行翻译。
tl; dr每个人的鼠标都应该用白色背景上的圆圈表示。 这是客户端的代码:
import socket
import sys
import pygame
from pygame.locals import *
import inputbox
import threading
import Queue
import time
host = ''
port = 0
server_port = 5000
FPS = 60 # frames per second, the general speed of the program
WINDOWWIDTH = 1280 # size of window's width in pixels
WINDOWHEIGHT = 720 # size of windows' height in pixels
GRAY = (100, 100, 100)
NAVYBLUE = ( 60, 60, 100)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 128, 0)
PURPLE = (255, 0, 255)
CYAN = ( 0, 255, 255)
BGCOLOR = WHITE
ALLCOLORS = (RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN)
def server_info_processing(name, sock, queue):
while True:
try:
while True:
data, addr = sock.recvfrom(1024)
queue.queue.clear()
queue.put(data)
except:
pass
def main():
players_pos = []
pygame.init()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
mousex = WINDOWWIDTH / 2
mousey = WINDOWHEIGHT / 2
s.bind((host, port))
s.setblocking(0)
q = Queue.Queue()
#server processing thread
sPThread = threading.Thread(target = server_info_processing, args = ("RecvThread", s, q))
sPThread.daemon = True
sPThread.start()
while True:
try:
answer = inputbox.ask(DISPLAYSURF, "Server IP")
s.sendto(str(mousex) + " " + str(mousey), (answer, server_port))
break
except Exception:
print "The IP address you entered is either not currently available or doesn't exist."
while True:
try:
players_pos = q.get_nowait()
q.task_done()
players_pos = eval(players_pos) #The server is returning a string, but we need a list.
except Queue.Empty:
pass
DISPLAYSURF.fill(BGCOLOR)
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
#send a msg to have the server delete this connection
print "Quitting."
s.sendto('quit', (answer, server_port))
pygame.quit()
s.close()
sys.exit()
elif event.type == MOUSEMOTION:
mousex, mousey = event.pos
s.sendto(str(mousex) + " " + str(mousey), (answer, server_port))
else:
pygame.event.clear()
allcolors_index = 0
for index, value in enumerate(players_pos):
if allcolors_index < len(ALLCOLORS):
current_color = ALLCOLORS[allcolors_index]
else:
allcolors_index = 0
current_color = ALLCOLORS[allcolors_index]
if value:
pygame.draw.circle(DISPLAYSURF, current_color, (int(players_pos[index][1][0]), int(players_pos[index][1][1])), 50)
allcolors_index += 1
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == '__main__':
main()
这是服务器:
import socket
import time
import threading
host = ''
port = 5000
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
peoples_pos = []
in_database = False
addr_location = None
print "Server Started"
while True:
try:
data, addr = s.recvfrom(1024)
for index, value in enumerate(peoples_pos):
if data == 'quit':
if addr == peoples_pos[index][0]:
#removing the item at the index that contains addr
del peoples_pos[index]
elif addr == peoples_pos[index][0]:
in_database = True
addr_location = index
if data != 'quit':
if in_database == False:
peoples_pos.append([])
peoples_pos[(len(peoples_pos)-1)].append(addr)
peoples_pos[(len(peoples_pos)-1)].append(data.split())
else:
peoples_pos[addr_location][1] = data.split()
in_database = False
print time.ctime(time.time()), peoples_pos
for index, value in enumerate(peoples_pos):
s.sendto(str(peoples_pos), peoples_pos[index][0])
except Exception as e:
pass
s.close()
更新1:似乎客户端中的主要while循环只运行一次。如果在循环的底部放置一个print语句,则会打印文本,但只打印一次。我不知道为什么会这样,无论是症状还是原因,或两者兼而有之。
更新2:似乎使用q.get()通过停止脚本导致问题,直到队列中有项目为止。我不太清楚为什么。我已将其更改为queue.get_nowait()并添加了一个尝试除外。现在,当我移动鼠标时,圆圈会显示,但旧的圆圈不会被删除,客户端会在大约3秒钟后崩溃。
更新3:事实证明旧圈子已被删除,但服务器正在发送旧圈子的数据,就好像它是一个新玩家一样。我修复了那个bug然后让我的线程成为一个守护进程,因为除非它是一个守护进程,当我调用sys.exit()时,线程将不会退出,我必须关闭命令提示符才能恢复。据我所知,代码工作正常。以上是新的更正代码。