2013-08-20 65 views
0

好了,所以我使用python学习socket编程。我会在适当的时候转移到c。Socket编程与Python

我以为我会写一个无聊的游戏去学习与插座;随意使用源代码(.bmp文件是我在gimp中制作的50x50像素图像)。服务器在此时不起作用。 (我敢肯定,它挂在“c, addr = s.accept()”)

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

其次,我想实现这样的,我不超载的网络,并刺激我的ISP(互联网服务提供商,对于缺乏经验的开发者)的方式在服务器和客户端之间的通讯。有没有一种方法可以测试网络并查看服务器和客户端之间实际传递的信息量?

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

GameServer.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!") 

GameClient.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!") 
+1

你不太可能会导致你的ISP的问题一个简单的网络游戏。我不会太在意测量带宽使用情况。 – Amber

+0

这是一种解脱。呃...供将来参考,我将如何去测量带宽使用情况? – user2522001

回答

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一个客户端(比如说每秒)并且客户端将回拨服务器。然后你只需测量时间的差异。

+1

它真的是“标准方式”吗?这是两种方法之一;另一个用'select.select()'工作,如果证明不被阻塞,只调用'accept()'。 – glglgl

+0

@glglgl“标准方式”指的是“将服务器保持在一个单独的线程中”,以便其他代码可以正常工作。除了'select'(或任何其他异步的东西)根本不是标准的。与它一起工作是很困难的,只有当其他所有事情都失败时,它才被用作最后的手段(当效率很重要时)。 – freakish

+0

谢谢你,怪异。这是太棒了!我没有足够的客气话来描述你。 – user2522001