0

好的,所以我正在使用python学习套接字编程。我会在适当的时候转到 c。

我以为我会写一个愚蠢的游戏来学习套接字;您可以随意使用源代码(.bmp 文件是我在 gimp 中制作的 50x50 像素图像)。服务器此时不工作。(我很确定它挂在“c,addr = s.accept()”上)

我认为处理这个问题的一种方法是使用两个线程。一个线程来处理服务器端的通信。还有一个线程来处理游戏循环,也是服务器端。目标是能够在服务器和客户端上玩游戏。我读过'扭曲模块'可以处理多线程,我以前从未做过多线程,但它应该是相当重要的。

其次,我想以这样一种方式实现服务器和客户端之间的通信,这样我就不会使网络过载并激怒我的 ISP(互联网服务提供商,针对经验不足的开发人员)。有没有一种方法可以测试网络并查看服务器和客户端之间实际传递了多少信息?

现在,我只有少量信息在客户端和服务器之间传递(只有当玩家通过按下按钮与客户端或服务器交互时才会传递信息)。我应该使用更智能的消息传递模型吗?

游戏服务器.py

import pygame, sys, os
from pygame.locals import *
import socket

s = socket.socket()

host = socket.gethostname()
port = 6000
s.bind(('0.0.0.0',port))

s.listen(5)
#while True:
#   c, addr = s.accept()
#   print 'Got connection from', addr
#   c.send('Hi blork, I am not rational either, but this works.  So I am happy!')

#   c.close()


window = pygame.display.set_mode((640,50))

pygame.display.set_caption("My Trivial Network Game:  Get to the right side of the screen!")

class Ship():
    xvel = 0
    yvel = 0
    x = 0 
    y = 0
    image = pygame.image.load('ship.bmp')

    def physics(self):
        self.x += self.xvel
        self.y += self.yvel
        return self

class Bolt():
    xvel = 0
    yvel = 0 
    x = 640
    y = 0
    image = pygame.image.load('bolt.bmp')

    def physics (self):
        self.x += self.xvel
        self.y += self.yvel
        return self


def input(events):
    for event in events:
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit()
#           elif event.key == pygame.K_f:
#               ship.xvel = 2
            elif event.key == pygame.K_z:
                bolt.xvel = -4
                s.send('zap')
                pygame.display.set_caption("Oh no!  Jon's being a dork!!")
                c.close()
        if event.type == QUIT:
            sys.exit(0)

#def MakeShip():
#   pygame

ship = Ship()
bolt = Bolt()
box = pygame.Rect(0,0,640,50)

loopVal = 0
while True:
    pygame.draw.rect(window,(0,0,0),box,0)

    window.blit(ship.image, (ship.x,ship.y))
    window.blit(bolt.image, (bolt.x,bolt.y))

    if loopVal == 0:
        loopVal += 1
        c, addr = s.accept()
        print "Now have connection from address:  ", addr

    input(pygame.event.get())

    ship.physics()
    bolt.physics()

    pygame.display.update()

    if (ship.x > 640):
        pygame.display.set_caption("You win!")

游戏客户端.py

import pygame, sys, os
from pygame.locals import *
import socket

s = socket.socket()

host = socket.gethostname()
port = 6000

window = pygame.display.set_mode((640,50))

pygame.display.set_caption("My Small Network Game:  Get to the right side of the screen!")

class Ship():
    xvel = 0
    yvel = 0
    x = 0 
    y = 0
    image = pygame.image.load('ship.bmp')

    def physics(self):
        self.x += self.xvel
        self.y += self.yvel
        return self

class Bolt():
    xvel = 0
    yvel = 0 
    x = 640
    y = 0
    image = pygame.image.load('bolt.bmp')

    def physics (self):
        self.x += self.xvel
        self.y += self.yvel
        return self


def input(events):
    for event in events:
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit()
            elif event.key == pygame.K_f:
                ship.xvel = 2
#           elif event.key == pygame.K_z:
#               bolt.xvel = -4
#               pygame.display.set_caption("Oh no!  Jon's being a dork!!")
        if event.type == QUIT:
            sys.exit(0)

#def MakeShip():
#   pygame

ship = Ship()
bolt = Bolt()
box = pygame.Rect(0,0,640,50)

s.connect((host, port))
reply = s.recv(1024)

print reply

while True:

    pygame.draw.rect(window,(0,0,0),box,0)

    window.blit(ship.image, (ship.x,ship.y))
    window.blit(bolt.image, (bolt.x,bolt.y))

    input(pygame.event.get())

    ship.physics()
    bolt.physics()

    #reply = s.recv(1024)
    print "He replied with zap!"

    if reply == 'zap':
        bolt.xvel = -4
        pygame.display.set_caption("Oh no!  Jon's being a dork!!")

    pygame.display.update()

    if (ship.x > 640):
        pygame.display.set_caption("You win!")
4

1 回答 1

2

你是对的:s.accept()阻塞直到建立连接。标准方法是使用线程。这是最简单的用法:

from threading import Thread

def server():
    while True:
        c, addr = s.accept()
        print 'Got connection from', addr
        c.send('Hi blork...')
        c.close()

t = Thread(target=server)
t.start()

但是请注意,一旦建立连接,您应该侦听来自该套接字的传入数据。其中一个想法是为每个连接创建一个单独的线程:

from threading import Thread
from socket import SHUT_RDWR

def client(sock):
    while True:
        data = sock.recv(2048)
        if not data:
            break
        print data
    try:
        sock.shutdown(SHUT_RDWR)
        sock.close()
    except:
        pass

def server():
    while True:
        c, addr = s.accept()
        print 'Got connection from', addr
        c.send('Hi blork...')
        t = Thread(target=client, args=(c,))
        t.start()

t = Thread(target=server)
t.start()

如果您正在谈论一个游戏(一次可能不超过 20 个打开的连接),这应该足够有效。您不必为一些复杂的东西而烦恼,例如 Twisted(通常应该用作高流量服务器)。

至于 ISP:你根本不用担心。测试带宽的一种方法是再创建一个线程,该线程将 ping 客户端(例如每秒),客户端将回传服务器。然后你只需测量时间差。

于 2013-08-20T07:35:38.490 回答