Hello Josiah,
I am struggling a bit with the socket server/client issue…
I get recv and send to work, and push to some extend…
But the data_handle is doing nothing, I can get a push to end up in
the data_handle function of the server or the client, hence I can’t unpickle…
Below the wxwiki socket modified according yours and robin comments and a small socket client based on your last email. I might have misunderstood something ?
May be you will see something that I ( obviously) missed .
#-------------- Socket Server wxwiki modif—(socketserver3.py)-----------------
import wx
import wx.lib.newevent
import socket
import asyncore
import Queue
import threading
from cStringIO import StringIO
import cPickle
import struct
import asynchat
to_network = Queue.Queue()
LogEvent, EVT_LOG_EVENT = wx.lib.newevent.NewEvent()
#for high bandwidth applications, you are going to want to handle
the
#out_buffer via a different mechanism, perhaps similar to asynchat or
#otherwise
class DispatcherConnection(asynchat.async_chat):
def init(self, connection, mainwindow):
self.mainwindow = mainwindow
asynchat.async_chat.init(self, connection)
self.state = 0
self.set_terminator(4)
self.received = StringIO() #instead of cStringIO()
def push(self, structure):
ds = cPickle.dumps(structure)
#we use network-endian byte order
ds = struct.pack('>L', len(ds)) + ds
#asynchat.async_chat.push(ds)
asynchat.async_chat.push(self, ds)
def log(self, message):
self.mainwindow.LogString(message, sock=self)
def log_info(self, message, type='info'):
if type != 'info':
self.log(message)
def handle_close(self):
self.log("Connection dropped: %s"%(self.addr,))
self.close()
def collect_incoming_data(self, data):
self.received.write(data)
def
found_terminator(self):
self.state = not self.state
if self.state:
self.received.seek(0)
self.set_terminator(struct.unpack(‘>L’,self.received.read(4))[0])
self.received.clear()
else:
self.received.seek(0)
data = cPickle.load(self.received)
self.set_terminator(4)
self.received.clear()
self.handle_data(data)
#implement your client logic as a subclass by overriding handle_data
def handle_data(self, data):
self.log(“Received fromClient:”+data+“\n”)
print “Received fromClient:”+data
class QME_Dispatcher(DispatcherConnection):
inc_buffer = ‘’
def handle_read(self):
self.inc_buffer += self.recv(512)
while ‘\n’ in self.inc_buffer:
snd, self.inc_buffer = self.inc_buffer.split(‘\n’, 1)
snd += ‘\n’
self.log(“[QME_SocketServer]Line
from %s: %r \n”%(self.addr, snd))
self.send(‘[SERVERSEND]QME_SOCKETSERVER in qme dispatcher\n’)
print “in QME_Dispatcher”
self.push(‘[SERVERPUSH] QME_SOCKETSERVER in qme dispatcher\n’)
#self.send(‘[SerevrSend] Server sending test dictionary \n’)
#testdico={‘a’:1,‘b’:2}
#self.push(testdico)
self.log(“[ServerEcho]:”+str(snd)+“\n”)
class DispatcherServer(asyncore.dispatcher):
def init(self, host, port, mainwindow,
factory=QME_Dispatcher):
self.mainwindow = mainwindow
self.factory = factory
asyncore.dispatcher.init(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind((host, port))
self.listen(5)
def handle_accept(self):
self.connection, info = self.accept()
self.mainwindow.LogString("[SERVER]:Got connection: %s\n"%(info,), sock=self)
self.connection.send("[SERVER]:connection with Server Established\r\n")
self.factory(self.connection,
self.mainwindow)
def loop(): #used only with thread.
while 1:
while not to_network.empty():
message = to_network.get()
#process and handle message
···
#
#remember to validate any possible
#socket objects recieved from the GUI,
#they could already be closed
asyncore.poll(timeout=.01)
class MainWindow(wx.Frame):
def init(self, host, port, threaded=0):
wx.Frame.init(self, None, title=“SERVER - Listening port:” + str(port))
#add any other GUI objects here
sz = wx.BoxSizer(wx.VERTICAL)
self.log = wx.TextCtrl(self, -1, ‘’, style=wx.TE_MULTILINE|wx.TE_RICH2)
sz.Add(self.log, 1, wx.EXPAND|wx.ALL, 3)
self.Bind(EVT_LOG_EVENT, self.LogEvent)
DispatcherServer(host, port, self)
if not threaded:
self.poller = wx.Timer(self, wx.NewId())
self.Bind(wx.EVT_TIMER,
self.OnPollSocket)
#poll 50 times/second, should be enough for low-bandwidth apps
self.poller.Start(20, wx.TIMER_CONTINUOUS)
else:
t = threading.Thread(target=loop)
t.setDaemon(1)
t.start()
def LogString(self, message, **kwargs):
event = LogEvent(msg=message, **kwargs)
if threading.activeCount() == 1:
self.LogEvent(event)
else:
wx.PostEvent(self, event)
def LogEvent(self, evt):
self.log.AppendText(evt.msg)
if not evt.msg.endswith(‘\n’):
self.log.AppendText(‘\n’)
def OnPollSocket(self, evt):
asyncore.poll(timeout=0)
#add other methods as necessary
if name == ‘main’:
a = wx.App(0)
b = MainWindow(‘localhost’, 24060, 0)
b.Show(1)
a.MainLoop()
#— End of Socket Server ---------------------------------------------------
— Simple Socket Client -----------(socketclient26.py)-----------------------
import socket
import
pickle
from cStringIO import StringIO
import cPickle
import struct
import asynchat
import wx
import wx.lib.newevent
import sys
def OnPollSocket(evt):
#asyncore.poll(timeout=0) # I try to make more straightforward…
asynchat.asyncore.poll(timeout=0) # May be I am not correct…
class ClientDispatcherConnection(asynchat.async_chat):
def init(self, host, port):
asynchat.async_chat.init(self)
self.state = 0
self.set_terminator(4)
self.received = StringIO() #cStringIO not defined
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
def push(self, structure):
ds = cPickle.dumps(structure)
#we use network-endian byte order
ds = struct.pack(‘>L’, len(ds)) + ds
asynchat.async_chat.push(self,ds)
def log(self, message):
self.mainwindow.LogString(message, sock=self)
def log_info(self, message, type=‘info’):
if type != ‘info’:
self.log(message)
def handle_close(self):
self.log(“Connection dropped: %s”%(self.addr,))
self.close()
def collect_incoming_data(self, data):
self.received.write(data)
def found_terminator(self):
self.state = not self.state
if self.state:
self.received.seek(0)
self.set_terminator(struct.unpack(‘>L’,self.received.read(4))[0])
self.received.clear()
else:
self.received.seek(0)
data = cPickle.load(self.received)
self.set_terminator(4)
self.received.clear()
self.handle_data(data)
#implement your client logic as a subclass by overriding handle_data
def handle_data(self, data):
#self.log(“Received fromServer:”+data)
print “[ClientSocket]:Received fromServer:”+data
class MainWindow(wx.Frame):
def init(self, host, port, threaded=0):
wx.Frame.init(self, None, title=“CLIENT - Connected to Server port:” + str(port))
var = raw_input(“______ To Connect - Press [ENTER] to continue_________”)
try:
#— we start the socket
mySocket =ClientDispatcherConnection(host,port)
#self.Bind(EVT_LOG_EVENT, self.LogEvent)
self.poller = wx.Timer( self, wx.NewId())
self.Bind(wx.EVT_TIMER, OnPollSocket)
self.poller.Start(20, wx.TIMER_CONTINUOUS)
var = raw_input(“______ To Test Connection send/recv - Press [ENTER] to continue_________”)
mySocket.send(‘[CLIENT]:TEST FROM SOCKET
CLIENT\n’)
print mySocket.recv(512)
var = raw_input("______ Test another send/Recv - Press [ENTER] to continue_________")
mySocket.send('[CLIENT]DATAPAGE_REQUEST_START:777\n')
#normally I receive a push from the server so it should be handled
# by the handle_data ? but recv works...
print mySocket.recv(512)
var = raw_input("______ Test push/data
handling Connection - Press [ENTER] to continue_________“)
data = {‘clientdoc1’:1,‘clientdico2’:2}
mySocket.push(data)
# Then answer should be managed by
# the Handle_data of ClientDispacherConnection
# but I never reach this either socket-client or client-csocket
# I think I missed something…!
var = raw_input(”______Socket will be closed Press [ENTER] _________")
mySocket.close()
except Exception, inst:
print "[ERROR] Error while scoket access:"
print Exception,inst
var = raw_input("______ Press [ENTER] _________")
print " Program will Stop Here "
if name == ‘main’:
a = wx.App(0)
b = MainWindow(‘localhost’, 24060, 0)
#b.Show(1)
#a.MainLoop()
Just to avoid confusion no wx frame used
in order not to confuse it with the server window…
#------- End of Simple Socket Client
Josiah Carlson jcarlson@uci.edu a écrit :
Robert VERGNES wrote:
I have an issue with the modif of the echo server.
teh push method…
your original push is called the function but unrelated to an
existing - it seems to me - unless the ‘push’, pushes any instantiated
objects from asynchat ?
So I used the push of the instantiated object… but no more success…
here is my modif of your push:
def push(self, structure):
ds = cPickle.dumps(structure)
#we use network-endian byte order
ds = struct.pack(‘>L’, len(ds)) + ds
#asynchat.async_chat.push(ds) #Josiah’s call
self.push(ds) #my call
Indeed, the push() method on the DispatcherConnection object does take
arbitrary instances to pickle and send to another computer. At the end
of that script we call the original push() method on asynchat.async_chat,
because ‘self.push()’, what you have labeled as ‘#my call’, is the
method that was just called.
This is the exact same thing that is done when you do things like…
class myFrame(wx.Frame):
def init(self, …):
wx.Frame.init(self, …)
…
One more question : I shall sue the same archietcture for my client I
suppose. In this case what shall i use instead of
self.create_socket(…)
class ClientDispatcherConnection(asynchat.async_chat):
def init(self, host, port):
asynchat.async_chat.init(self)
self.state = 0
self.set_terminator(4)
self.received =
cStringIO()
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
…
Découvrez une nouvelle façon d’obtenir des réponses à toutes vos questions ! Profitez des connaissances, des opinions et des expériences des internautes sur Yahoo! Questions/Réponses.