0

Ok, so I'm using python to learn socket programming. I'll move on to c in due time.

I thought that I would write a silly game to learn sockets with; feel free to use the source code yourself (.bmp files are 50x50 pixel images that I made in gimp). The server does not work at this point. (I'm pretty sure that it's hanging on the "c, addr = s.accept()")

I think a way to handle this is by using two threads. One thread to handle the communication server-side. And one thread to handle the game loop, also server side. The goal is to be able to play the game on both the server and the client. I've read that the 'twisted module' can handle multi-threading, I've never done multi-threading before, but it's supposed to be fairly non-trivial to do.

Secondly, I want to implement the communication between the server and the client in such a way that I don't overload the network and irritate my ISP (Internet Service Provider, for the less experienced developers). Is there a way that I can test the network and see how much information is actually getting passed between the server and the clients?

Right now, I only have small amount of information being passed between the client and server (information is only passed when players interact with the client or server by pushing a button). Is there a smarter message passing model that I should use instead?

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!")
asked Aug 20, 2013 at 6:18
2
  • 1
    You are unlikely to cause problems with your ISP for a simple networked game. I wouldn't worry too much about measuring the bandwidth usage. Commented Aug 20, 2013 at 6:20
  • That's a relief. Umm... for future reference how would I go about measuring bandwidth usage? Commented Aug 20, 2013 at 6:28

1 Answer 1

2

You are correct: s.accept() blocks until connection is established. The standard way is to use threads. This is the simpliest usage:

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()

Note however that once the connection is established you should listen for incoming data from that socket. One of the ideas is to create a separate thread for each connection:

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()

If you are talking about a game (with probably no more then 20 open connections at a time) this should be efficient enough. You don't have to bother with some sophisticated stuff like Twisted (which generally is supposed to be used as a high traffic server).

As for ISP: you should not worry about that at all. One way to test bandwidth is to create yet one more thread which will ping a client (say every second) and the client will pong back the server. Then you just measure the difference in time.

answered Aug 20, 2013 at 7:35
Sign up to request clarification or add additional context in comments.

3 Comments

Is it really "the standard way"? It is one of two approaches; the other one works with select.select() and only calls accept() if it is proved not to block.
@glglgl "the standard way" refers to "keep the server in a seperate thread" so that the rest of the code can work without issues. Besides select (or any other asynchronous stuff) is not standard at all. It's difficult to work with it and it should be used only as a last resort (when efficiency matters) when everything else fails.
Thank you, freakish. This is fantastic! There aren't enough kind words that I can use to describe you.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.