Sending pygames-event data to a twisted-server? - python

I'm running a pygames program with twisted and I'm having problems when it comes to sending data from within a pygame event.
First here is the server:
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
import simplejson
class Game_Data(LineReceiver):
def __init__(self, players, clients):
self.players = players
self.clients = clients
## the connectionMade method of LineReceiver is being used to create ##
## protocol instances of each client so it can send back any data it gets ##
def connectionMade(self):
new_player = 'player_' + str(len(self.players) + 1)
self.clients.append(self)
self.players.append(new_player)
self.players = simplejson.dumps(self.players)
for client in self.clients:
client.sendLine(self.players)
## what ever data the server receives it sends right back to any clients ##
def lineReceived(self,line):
self.line = line
print self.line
for client in self.clients:
client.sendLine(self.line)
class BlackFactory(Factory):
def __init__(self):
self.players = []
self.clients = []
def buildProtocol(self, addr):
return Game_Data(self.players, self.clients)
reactor.listenTCP(6000, BlackFactory())
Now for the client:
import pygame
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet.task import LoopingCall
from twisted.internet import reactor
class BlackClientProtocol(LineReceiver):
def __init__(self, recv, host):
self.recv = recv
self.host = host
def lineReceived(self, line):
self.recv(line)
print line ## prints out as expected ##
def connectionMade(self):
self.host = self
print self.host ## prints out as expected ##
class BlackClient(ClientFactory):
def __init__(self, recv, host):
self.recv = recv
self.host = host
def buildProtocol(self, addr):
return BlackClientProtocol(self.recv, self.host)
class Client(object):
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((800, 600))
pygame.display.flip()
reactor.callLater(0.1, self.tick)
def new_line(self, line):
self.line = line
## this trial_func was to see if I could pass the BlackClient another argument ##
## to return an instance of the protocol to be called later in this class ##
def trial_func(self, host):
self.host = host
def tick(self):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
print self.line ## prints out as expected##
print self.host ## does not print out ???##
if __name__ == '__main__':
c = Client()
lc = LoopingCall(c.tick)
lc.start(0.1)
reactor.connectTCP('192.168.1.2', 6000, BlackClient(c.new_line, c.trial))
reactor.run()
Edit: This is a more explicit example of whats going on. With the comments being the hang-ups. As long as you have pygames installed this will run, with the pygame event being a simple KEYDOWN (escape key) event as the trigger for the client to send data.

I looked at your code and this seems to be the relevant part:
def tick(self):
flag = 0
for event in pygame.event.get():
...
## call an instance of the protocol and sendLine ##
BlackClient(self.new_line(allhands)) ## this line does not work ##
## send allhands data ##
...
You want so send data back to the server, but here you're just creating a new instance of BlackClient.
You probably want to use sendLine to send the line, but you need a reference to the current protocoll instance (or at least to this method).
This is an example how you could achieve this:
class Client(object):
...
# this method is going to be replaced
def sendLine(self, line):
pass
def tick(self):
flag = 0
for event in pygame.event.get():
...
## call sendLine, which is replaced by the sendLine method from the protocol ##
self.sendLine(yourStuff)
class BlackClient(ClientFactory):
def __init__(self, client):
# keep instance of client
self.client = client
def buildProtocol(self, addr):
# give client.new_line method to protocol
proto = BlackClientProtocol(self.client.new_line)
# replace client's sendLine with proto.sendLine
self.client.sendLine = proto.sendLine
return proto
if __name__ == '__main__':
c = Client()
lc = LoopingCall(c.tick)
lc.start(0.1)
protocoll =
reactor.connectTCP('192.168.1.2', 6000, BlackClient(c))
reactor.run()
This is just an example; you could probably clean up the code a bit. Maybe you want to use some kind of dispatcher (like pydispatch)

Related

Receiving zmq message with error every one hour

I should say, that before I've started to use zmq reactor instead of poller everything worked fine.
class BaseZmqReceiver(BaseZmqNode):
__metaclass__ = ABCMeta
def __init__(self, host, port, hwm, bind, on_receive_callback):
super(BaseZmqReceiver, self).__init__(host=host, port=port, bind=bind, hwm=hwm)
self.node.on_message_callback = on_receive_callback
self.stream = ZMQStream(self.socket)
self.stream.on_recv(self.on_message_received)
ZmqLoopRunner().start()
def on_message_received(self, message):
return self.node.on_message_callback(message)
def create_node(self):
return ReceivingNode(None, None)
class ZmqLoopRunner(Thread):
def __init__(self):
super(ZmqLoopRunner, self).__init__()
self.loop = IOLoop.instance()
self.daemon = True
def run(self):
self.loop.start()
def stop(self):
self.loop.stop()
class ZmqSubscriber(BaseZmqReceiver):
def __init__(self, host, port, on_receive_callback, bind=False, hwm=1000):
super(ZmqSubscriber, self).__init__(host=host, port=port, hwm=hwm, bind=bind,
on_receive_callback=on_receive_callback)
def create_socket(self):
socket = self.context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, "")
return socket
Here is my zmq code.
And I'm basically just receiving multipart message in callback.
def on_message(message):
part1, part2 = message
And every one hour I've got message that consist of only one part. So I got
TypeError: need more than one value to unpack.
EDIT here is my full zmq code.
https://drive.google.com/file/d/0B7jQezPDaLZFQWxBMUdXQkxnS1k/edit?usp=sharing

Python socket hangs program

I am working on a simple HTTP server in Python. I am taking bits and pieces from here: http://hg.python.org/cpython/file/3.3/Lib/socketserver.py to see how Python's standard library handles it.
My problem is that as soon as I try to accept requests my program hangs. Here is my code its only 100 lines so I'll just post it directly here.
I have a process() function which is in a loop that loops forever and it's suppose to handle new connections. Inside I have a print statement that only gets printed once.
print('processing') in TCPServer.process()
I have tried threading off process() but I get the same result.
"""."""
import socket
import select
from abc import abstractmethod, ABCMeta
class BaseServer(metaclass=ABCMeta):
def __init__(self, server_address, server_port, RequestHandlerClass):
self._server_address = server_address
self._server_port = server_port
self._RequestHandlerClass = RequestHandlerClass
self._running = False
def serve_forever(self):
self._running = True
while self._running:
self.process()
#abstractmethod
def process(self):
pass
def shutdown(self):
self._running = False
class TCPServer(BaseServer):
def __init__(self,
server_address,
server_port,
RequestHandlerClass,
address_family=socket.AF_INET,
socket_type=socket.SOCK_STREAM,
request_queue_size=1,
bind=True):
super(TCPServer, self).__init__(server_address,
server_port,
RequestHandlerClass)
self._address_family = address_family
self._socket_type = socket_type
self._request_queue_size = request_queue_size
self._socket = socket.socket(self._address_family, self._socket_type)
self._read_list = [self._socket]
if bind:
self.bind()
def bind(self):
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket.bind((self._server_address, self._server_port))
self._socket.listen(self._request_queue_size)
def shutdown(self):
super().shutdown()
self._socket.close()
def process(self):
print('processing')
readable, writeable, errored = select.select(self._read_list, [], [])
for socket in readable:
if socket is self._socket:
client_socket, client_address = self._socket.accept()
self._read_list.append(client_socket)
print('connection from: ', client_address)
else:
self._RequestHandlerClass(client_socket)
self._read_list.remove(client_socket)
class BaseRequestHandler(metaclass=ABCMeta):
def __init__(self, client_socket):
self._client_socket = client_socket
self.setup()
try:
self.handle()
finally:
self.finish()
#abstractmethod
def setup(self):
pass
#abstractmethod
def handle(self):
pass
#abstractmethod
def finish(self):
pass
class HTTPRequestHandler(BaseRequestHandler):
def setup(self):
print('REQUEST SETUP')
print(self._client_socket.recv(2048))
def handle(self):
print('REQUEST HANDLE')
def finish(self):
print('REQUEST FINISH')
self._client_socket.close()
if __name__ == '__main__':
tcp_server = TCPServer(server_address='',
server_port=9000,
RequestHandlerClass=HTTPRequestHandler)
tcp_server.serve_forever()
I ran your code but couldn't make it hang. However, there is a fatal error in your process() function where you refer to client_socket in the else: branch, but client_socket is not defined at that point. You probably meant to refer to socket.
I was able to make two connections to the server on port 9000, and get "connection from:" lines for each. As soon as one of those connections sent something, your server would crash for the above reason.

Python, Call a class function from another class

Can you anyone please help me (noob) call the broadcast function from class BroadcastServerFactory in class process, as per attached code
I have tried so many methods of call a function from another class, but no solution
import time, sys
from apscheduler.scheduler import Scheduler
import threading
import socket
from twisted.internet import reactor
from twisted.python import log
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
class process(threading.Thread):
def __init__(self, buffer3):
threading.Thread.__init__(self)
self.setDaemon(True)
self.buffer3 = buffer3
def run(self):
factory.broadcast("I don't know what I'm doing!")
class BroadcastServerProtocol(WebSocketServerProtocol):
def onOpen(self):
self.factory.register(self)
def onMessage(self, msg, binary):
if not binary:
self.factory.broadcast("'%s' from %s" % (msg, self.peerstr))
def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)
class BroadcastServerFactory(WebSocketServerFactory):
"""
Simple broadcast server broadcasting any message it receives to all
currently connected clients.
"""
def __init__(self, url, debug = False, debugCodePaths = False):
WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
self.clients = []
self.tickcount = 0
self.tick()
def tick(self):
self.tickcount += 1
self.broadcast("'tick %d' from server" % self.tickcount)
reactor.callLater(1, self.tick)
def register(self, client):
if not client in self.clients:
print "registered client " + client.peerstr
self.clients.append(client)
def unregister(self, client):
if client in self.clients:
print "unregistered client " + client.peerstr
self.clients.remove(client)
def broadcast(self, msg):
print "broadcasting message '%s' .." % msg
for c in self.clients:
c.sendMessage(msg)
print "message sent to " + c.peerstr
class BroadcastPreparedServerFactory(BroadcastServerFactory):
"""
Functionally same as above, but optimized broadcast using
prepareMessage and sendPreparedMessage.
"""
def broadcast(self, msg):
print "broadcasting prepared message '%s' .." % msg
preparedMsg = self.prepareMessage(msg)
for c in self.clients:
c.sendPreparedMessage(preparedMsg)
print "prepared message sent to " + c.peerstr
def testing():
buffer2 - "hello"
myDisplay = process(buffer2)
myDisplay.start()
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'debug':
log.startLogging(sys.stdout)
debug = True
else:
debug = False
level_scheduler = Scheduler()
level_scheduler.add_interval_job(testing, seconds=5)
level_scheduler.start()
#ServerFactory = BroadcastServerFactory
ServerFactory = BroadcastPreparedServerFactory
factory = ServerFactory("ws://localhost:9000",
debug = debug,
debugCodePaths = debug)
factory.protocol = BroadcastServerProtocol
factory.setProtocolOptions(allowHixie76 = True)
listenWS(factory)
webdir = File(".")
web = Site(webdir)
reactor.listenTCP(8080, web)
reactor.run()
Thanks
Pass the class instance of BroadcastServerFactory to be called to the class instance that calls it process on creation
class process(threading.Thread):
def __init__(self, buffer3m, broadcast_server_factory):
threading.Thread.__init__(self)
self.setDaemon(True)
self.buffer3 = buffer3
self.factory = broadcast_server_factory
def run(self):
self.factory.broadcast("I don't know what I'm doing!")
and then call it (it's assigned as self.factory in the run statement. I can't see where you create a process class in your __main__ but it will be created with something like
p = process(buffer, factory)
Aside: Using capital letters for class names is considered good form in python process -> Process

How do i control what socket thread I want to connect to in a asychronous reverse server python?

Good evening, This is my 1st time on this site, I have been programming a python based user monitoring system for my work for the past 3 months and I am almost done with my 1st release. However I have run into a problem controlling what computer I want to connect to.
If i run the two sample code I put in this post I can receive the client and send commands to client with the server, but only one client at a time, and the server is dictating which client I can send to and which one is next. I am certain the problem is "server side but I am not sure how to fix the problem and a Google search does not turn up anyone having tried this.
I have attached both client and server base networking code in this post.
client:
import asyncore
import socket
import sys
do_restart = False
class client(asyncore.dispatcher):
def __init__(self, host, port=8000):
serv = open("srv.conf","r")
host = serv.read()
serv.close()
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
def writable(self):
return 0
def handle_connect(self):
pass
def handle_read(self):
data = self.recv(4096)
#Rest of code goes here
serv = open("srv.conf","r")
host = serv.read()
serv.close()
request = client(host)
asyncore.loop()
server:
import asyncore
import socket
import sys
class soc(asyncore.dispatcher):
def __init__(self, port=8000):
asyncore.dispatcher.__init__(self)
self.port = port
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(('', port))
self.listen(5)
def handle_accept(self):
channel, addr = self.accept()
while 1:
j = raw_input(addr)
#Rest of my code is here
server = soc(8000)
asyncore.loop()
Here is a fast and dirty idea that I threw together.
The use of raw_input has been replaced with another dispatcher that is asyncore compatable, referencing this other question here
And I am expanding on the answer given by #user1320237 to defer each new connection to a new dispatcher.
You wanted to have a single command line interface that can send control commands to any of the connected clients. That means you need a way to switch between them. What I have done is created a dict to keep track of the connected clients. Then we also create a set of available commands that map to callbacks for your command line.
This example has the following:
list: list current clients
set <client>: set current client
send <msg>: send a msg to the current client
server.py
import asyncore
import socket
import sys
from weakref import WeakValueDictionary
class Soc(asyncore.dispatcher):
CMDS = {
'list': 'cmd_list',
'set': 'cmd_set_addr',
'send': 'cmd_send',
}
def __init__(self, port=8000):
asyncore.dispatcher.__init__(self)
self._conns = WeakValueDictionary()
self._current = tuple()
self.port = port
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
self.cmdline = Cmdline(self.handle_input, sys.stdin)
self.cmdline.prompt()
def writable(self):
return False
def handle_input(self, i):
tokens = i.strip().split(None, 1)
cmd = tokens[0]
arg = ""
if len(tokens) > 1:
arg = tokens[1]
cbk = self.CMDS.get(cmd)
if cbk:
getattr(self, cbk)(arg)
self.cmdline.prompt(self._addr_to_key(self._current))
def handle_accept(self):
channel, addr = self.accept()
c = Conn(channel)
self._conns[self._addr_to_key(addr)] = c
def _addr_to_key(self, addr):
return ':'.join(str(i) for i in addr)
def cmd_list(self, *args):
avail = '\n'.join(self._conns.iterkeys())
print "\n%s\n" % avail
def cmd_set_addr(self, addr_str):
conn = self._conns.get(addr_str)
if conn:
self._current = conn.addr
def cmd_send(self, msg):
if self._current:
addr_str = self._addr_to_key(self._current)
conn = self._conns.get(addr_str)
if conn:
conn.buffer += msg
class Cmdline(asyncore.file_dispatcher):
def __init__(self, cbk, f):
asyncore.file_dispatcher.__init__(self, f)
self.cbk = cbk
def prompt(self, msg=''):
sys.stdout.write('%s > ' % msg)
sys.stdout.flush()
def handle_read(self):
self.cbk(self.recv(1024))
class Conn(asyncore.dispatcher):
def __init__(self, *args, **kwargs):
asyncore.dispatcher.__init__(self, *args, **kwargs)
self.buffer = ""
def writable(self):
return len(self.buffer) > 0
def handle_write(self):
self.send(self.buffer)
self.buffer = ''
def handle_read(self):
data = self.recv(4096)
print self.addr, '-', data
server = Soc(8000)
asyncore.loop()
Your main server is now never blocking on stdin, and always accepting new connections. The only work it does is the command handling which should either be a fast operation, or signals the connection objects to handle the message.
Usage:
# start the server
# start 2 clients
>
> list
127.0.0.1:51738
127.0.0.1:51736
> set 127.0.0.1:51736
127.0.0.1:51736 >
127.0.0.1:51736 > send foo
# client 127.0.0.1:51736 receives "foo"
To me
while 1:
j = raw_input(addr)
seems to be the problem:
you only accept a socket an then do something with it until end.
You should create e new dispatcher for every client connecting
class conn(asyncore.dispatcher):
...
def handle_read(self):
...
class soc(asyncore.dispatcher):
def handle_accept(self):
...
c = conn()
c.set_socket(channel)
Asyncore will call you back for every read operation possible.
Asyncore uses only one thread. This is its strength. every dispatcher that has a socket is called one after an other with those handle_* functions.

Twisted task.loop and pb auth

Learn Twisted. I decided to write a server and client that once a second to share data.
Wrote one implementation, but it seems to me that it is not correct.
# -*- coding: utf-8 -*-
from twisted.spread import pb
from twisted.internet import reactor, task
from twisted.cred import credentials
from win32com.server import factory
class login_send:
def __init__(self):
self.count=0
self.timeout = 1.0
self.factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8800, self.factory)
def testTimeout(self):
self.count+=1
print self.count
def1 = self.factory.login(credentials.UsernamePassword("test1","bb1b"))
def1.addCallbacks(self.good_connected, self.bad_connected)
def1.addCallback(self.send_data)
def1.addErrback(self.disconnect)
if self.count>10:def1.addBoth(self.disconnect)
def start(self):
l = task.LoopingCall(self.testTimeout)
l.start(self.timeout)
reactor.run()
def good_connected(self, perspective):
print 'good login and password', perspective
return perspective
def bad_connected(self, perspective):
print 'bad login or password', perspective
return perspective
def send_data(self, perspective):
print 'send'
return perspective.callRemote("foo", self.count)
def disconnect(self, perspective):
print 'disconnect'
reactor.stop()
if __name__ == "__main__":
st=login_send()
st.start()
Code: if login and password True -> send self.count, if login or password False -> disconnect, if self.count>10 -> disconnect
The first mistake, in my opinion is that I have to login every time.
def1 = self.factory.login(credentials.UsernamePassword("test1", "bb1b"))
How to make one authorization, and continue to send data every second?
simple test server code:
from zope.interface import implements
from twisted.spread import pb
from twisted.cred import checkers, portal
from twisted.internet import reactor
class MyPerspective(pb.Avatar):
def __init__(self, name):
self.name = name
def perspective_foo(self, arg):
print "I am", self.name, "perspective_foo(",arg,") called on", self
return arg
class MyRealm:
implements(portal.IRealm)
def requestAvatar(self, avatarId, mind, *interfaces):
if pb.IPerspective not in interfaces:
print 'qqqq'
raise NotImplementedError
return pb.IPerspective, MyPerspective(avatarId), lambda:None
p = portal.Portal(MyRealm())
c = checkers.InMemoryUsernamePasswordDatabaseDontUse(test1="bbb",
user2="pass2")
p.registerChecker(c)
reactor.listenTCP(8800, pb.PBServerFactory(p))
reactor.run()
I believe this should do the trick.
# Upper case first letter of class name is good policy.
class Login_send:
def __init__(self):
# initialize the state variable to False.
self.connection = False
self.count=0
self.timeout = 1.0
self.factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8800, self.factory)
def testTimeout(self):
self.count+=1
print self.count
# no connection -- create one.
if not self.connection:
self.assign_connection()
# cached connection exists, call send_data manually.
elif self.count > 10:
self.disconnect(self.connection)
else:
#you probably want to send data only if it it should be valid.
self.send_data(self.connection)
def assign_connection(self):
''' Creates and stores a Deffered which represents the connection to
the server. '''
# cache the connection.
self.connection = self.factory.login(
credentials.UsernamePassword("test1","bb1b"))
# add connection callbacks as normal.
self.connection.addCallbacks(
self.good_connected, self.bad_connected)
self.connection.addCallback(self.send_data)
self.connection.addErrback(self.disconnect)
def disconnect(self, perspective):
# be sure to cleanup after yourself!
self.connection = False
print 'disconnect'
reactor.stop()
# the rest of your class goes here.

Categories

Resources