# -*- coding: utf-8 -*-
from copy import deepcopy, copy
from pdb import set_trace as st
from os import fork, pipe, read, write, close, fdopen
from sys import exit
from socket import *
from select import poll, POLLIN, POLLPRI, POLLHUP, POLLERR, POLLOUT
from select import error as select_error
import Queue
from time import sleep
import signal
from game import Game, NetException
import sys
reload(sys)
sys.setdefaultencoding('utf8')
def input_edit(str):
return str.strip()
def sig_handler(signal, frame):
global message_queues, server, net_loop
server.close()
signal.signal(signal.SIGINT, sig_handler)
HOST = None
PORT = 4500
# Keep up with the queues of outgoing messages
message_queues = {}
# flag to main network loop
net_loop = 1
index = 0
# initiate game obj
Game = Game()
# poll flags
READ_ONLY = POLLIN | POLLPRI | POLLHUP | POLLERR
READ_WRITE = READ_ONLY | POLLOUT
for res in getaddrinfo(HOST, PORT, AF_INET, SOCK_STREAM):
af, socktype, proto, canonname, sa = res
# create server socket and binding it to address
server = socket(af, socktype, proto)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # TIME_WAIT
server.bind(sa)
server.listen(0)
server.setblocking(0)
# Map file descriptors to socket objects
fd_to_socket = { server.fileno(): server,
}
poller = poll()
poller.register(server, READ_ONLY)
while net_loop:
try:
events = poller.poll(250)
except select_error: # usually cause by Ctrl+C SIGINT Signal
print "Exiting main network loop"
break
# check data to bw written
for key,vl in fd_to_socket.iteritems():
poller.modify(vl, READ_WRITE)
for fd, flag in events:
s = fd_to_socket[fd]
# some checks
if flag & (POLLIN | POLLPRI):
if s is server: # new connection
connection, client_addr = s.accept()
print "Connected ", client_addr
connection.setblocking(0)
fd_to_socket[ connection.fileno() ] = connection
poller.register(connection, READ_ONLY)
message_queues[connection] = Queue.Queue()
Game.new_connection(connection)
else: # reading new data
data = s.recv(1024)
if data:
data = input_edit(data)
Game.new_data(s, data)
print "From %s received: %s" % (s.getpeername(), data)
poller.modify(s, READ_WRITE)
else: # empty string, client disconnecting
print "Closing connection %s after reading no data"
poller.unregister(s)
s.close()
del message_queues[s]
del fd_to_socket[fd]
elif flag & POLLHUP: # client dirty hangup connection
print "Clossing connection from %s after HANGUP" % s.getpeername()
poller.unregister(s)
s.close()
# del message_queues
del message_queues[s]
del fd_to_socket[fd]
elif flag & POLLOUT: # ready send data to client
try:
# st()
# next_msg = message_queues[s].get_nowait()
next_msg = Game.send_to_user(s)
except Queue.Empty:
# no writable data, so stop monitoring this connection for write
poller.modify(s, READ_ONLY)
# print "Nothing to send to %s" % str(s.getpeername())
except NetException:
poller.modify(s, READ_ONLY)
else:
print "Send '%s' to %s" % (next_msg, s.getpeername())
s.send(next_msg)
elif flag & POLLERR: # closing connection on some error
print "Clossing connection from %s after Exception" % s.getpeername()
poller.unregister(s)
s.close()
del message_queues[s]
del fd_to_socket[fd]
# check data to bw written
if index % 2 == 0:
for key,vl in fd_to_socket.iteritems():
poller.modify(vl, READ_WRITE)
# if index == 10:
# break
index += 1
server.close()