2013-08-20 10 views
0

좋아, 그래서 나는 소켓 프로그래밍을 배우는 데 Python을 사용하고 있습니다. 나는 기한 내에 C로 이동할 것이다.소켓 프로그래밍과 파이썬

나는 소켓을 배울 바보 같은 게임을 쓸 것이라고 생각했다; 직접 (.bmp 파일은 내가 만든 김프에서 만든 50x50 픽셀 이미지입니다) 소스 코드를 자유롭게 사용하십시오. 이 시점에서 서버가 작동하지 않습니다. (나는 그것이 "c, addr = s.accept()"에 걸려 있음을 확신한다)

나는 이것을 처리하는 방법이 두 개의 스레드를 사용하는 것이라고 생각한다. 통신 서버 측을 처리하는 하나의 스레드. 그리고 하나의 스레드가 게임 루프를 처리하기 위해 또한 서버 측에 있습니다. 목표는 서버와 클라이언트 모두에서 게임을 할 수있게하는 것입니다. 필자는 'twisted module'이 멀티 스레딩을 처리 할 수 ​​있다는 것을 읽었습니다. 전에는 멀티 스레딩을 해본 적이 없지만, 그렇게하기는 쉽지 않습니다.

둘째, 나는 네트워크에 과부하가 걸리지 않고 ISP (Internet Service Provider)에 짜증을 내지 않는 방식으로 서버와 클라이언트 간의 통신을 구현하려고합니다. 네트워크를 테스트하여 실제로 서버와 클라이언트간에 얼마나 많은 정보가 전달되는지 볼 수있는 방법이 있습니까?

지금은 정보가 적은 양의 정보 만 클라이언트와 서버간에 전달됩니다 (플레이어가 버튼을 눌러 클라이언트 나 서버와 상호 작용할 때만 정보가 전달됩니다). 그 대신에 사용해야하는 더 똑똑한 메시지 전달 모델이 있습니까?

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을 수행하는 스레드를 한 번 더 만드는 것입니다 (매초 말). 그러면 클라이언트가 서버를 다시 퐁 (pong)합니다. 그런 다음 시간의 차이 만 측정하면됩니다.

+1

정말 "표준 방식"입니까? 그것은 두 가지 접근법 중 하나입니다. 다른 하나는'select.select()'와 함께 작동하고 차단하지 않는 것으로 입증되면'accept()'만 호출합니다. – glglgl

+0

@glglgl "표준 방식"은 "코드를 별도의 스레드에 보관"하여 나머지 코드가 문제없이 작동 할 수 있도록합니다. 'select' (또는 다른 비동기적인 것들) 외에는 전혀 표준이 아닙니다. 작업하기가 어렵고 모든 것이 실패 할 때 최후의 수단으로 만 사용해야합니다 (효율성 문제). – freakish

+0

고맙습니다. 굉장해! 내가 당신을 묘사하는 데 사용할 수있는 친절한 단어가 충분하지 않습니다. – user2522001