2013-08-20 99 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