I'm working on a program in python using rpyc. My goal is to create a simple server that accepts bytes of data (String) from a client. I'm new both to python and rpyc.
Here is my server.py code:
from rpyc.utils.server import ThreadedServer # or ForkingServer
class MyService(rpyc.Service):
# My service
pass
if __name__ == "__main__":
server = ThreadedServer(MyService, port = 18812)
server.start()
Then there is my client.py code:
from rpyc.core.stream import SocketStream
from rpyc.core.channel import Channel
b = SocketStream.connect("localhost", 18812)
c = Channel(b, compress=True)
c.send("abc")
b.close()
c.close()
Yet when running my client.py there is an error in console. If I'm understanding it correctly, i must create a stream in server.py that is associated with the client. Is that the case? How can i achieve that?
You're using the low level primitives, but you didn't put a Protocol over those. Anyway, you really don't need to go there. Here's what you want to do:
myserver.py
import rpyc
from rpyc.utils.server import ThreadedServer
class MyService(rpyc.Service):
# My service
def exposed_echo(self, text):
print(text)
if __name__ == "__main__":
server = ThreadedServer(MyService, port = 18812)
server.start()
then open a python shell and try
>>> import rpyc
>>> c = rpyc.connect("localhost", 18812)
>>> c.root.echo("hello")
'hello'
note that this is using the service-oriented mode. you can also use the classic mode. just run bin/rpyc_classic.py and then connect using rpyc.classic.connect("host")
Related
I am trying to use GLib.IOChannels to send data from a client to a server running a Glib.Mainloop.
The file used for the socket should be located at /tmp/so/sock, and the server should simply run a function whenever it receives data.
This is the code I've written:
import sys
import gi
from gi.repository import GLib
ADRESS = '/tmp/so/sock'
def server():
loop = GLib.MainLoop()
with open(ADRESS, 'r') as sock_file:
sock = GLib.IOChannel.unix_new(sock_file.fileno())
GLib.io_add_watch(sock, GLib.IO_IN,
lambda *args: print('received:', args))
loop.run()
def client(argv):
sock_file = open(ADRESS, 'w')
sock = GLib.IOChannel.unix_new(sock_file.fileno())
try:
print(sock.write_chars(' '.join(argv).encode('utf-8'), -1))
except GLib.Error:
raise
finally:
sock.shutdown(True)
# sock_file.close() # calling close breaks the script?
if __name__ == '__main__':
if len(sys.argv) > 1:
client(sys.argv[1:])
else:
server()
When called without arguments, it acts as the server, if called with arguments, it sends them to a running server.
When starting the server, I immediately get the following output:
received: (<GLib.IOChannel object at 0x7fbd72558b80 (GIOChannel at 0x55b8397905c0)>, <flags G_IO_IN of type GLib.IOCondition>)
I don't know why that is. Whenever I send something, I get an output like (<enum G_IO_STATUS_NORMAL of type GLib.IOStatus>, bytes_written=4) on the client side, while nothing happens server-side.
What am I missing? I suspect I understood the documentation wrong, as I did not find a concrete example.
I got the inspiration to use the IOChannel instead of normal sockets from this post: How to listen socket, when app is running in gtk.main()?
I'm trying to add a new module to a connection.
I have the following files:
main.py
UpdateDB.py
In UpdateDB:
def UpdateDB():
...
In main.py:
import UpdateDB
import rpyc
conn = rpyc.classic.connect(...)
rpyc.utils.classic.upload_package(conn, UpdateDB)
conn.modules.UpdateDB.UpdateDB()
And I can figure out how to invoke the UpdateDB() function.
I get:
AttributeArror: 'module' object has no attribute 'UpdateDB'
Perhaps I'm trying to do it wrong. So let me explain what I'm trying to do:
I want to create a connection to the server and run on it a function from the UpdateDB.py file.
Not sure how to do that in classic mode (not sure why you'd use it), but here is how to accomplish the task in the newer RPyC service mode.
Script ran as Server:
import rpyc
from rpyc.utils.server import ThreadedServer
class MyService(rpyc.Service):
def exposed_printSomething(self, a):
print a
print "printed on server!"
return 'printed on client!'
if __name__ == '__main__':
server = ThreadedServer(MyService, port=18812)
server.start()
Script ran as Client:
import rpyc
if __name__ == '__main__':
conn = rpyc.connect("127.0.0.1", port=18812)
print conn.root.printSomething("passed to server!")
Result on Server:
passed to server!
printed on server!
Result on Client:
printed on client!
today I was working to create some unittests for my application: a websocket client..
In the real world, ws server is an embeeded pc in the home network.
Now, for my unittest, I'd like to create a fake ws server and use it to test the client.
can you suggest me some ws-server plug&play that I can call inside my unittest setup and use it for testing?
I tried to use Autobahn ws server, but it is not plug&play.. It should work but I'm not able to handle correctly it in a separate thread.
My goal is to test the client not to develop a dummy server.
Can you help me with something easy and ready-to-use?
Thanks in advance,
Salvo
Here the minimal code, I wrote, in order to avoid the blocking command (serve_forever)
I used ws4py as websocket library.
from wsgiref.simple_server import make_server
from ws4py.websocket import WebSocket
from ws4py.server.wsgirefserver import WSGIServer, WebSocketWSGIRequestHandler
from ws4py.server.wsgiutils import WebSocketWSGIApplication
import threading
class TestWebSocket(WebSocket):
def received_message(self, message):
self.send("+OK", False)
class TestServer:
def __init__(self, hostname='127.0.0.1', port=8080):
self.server = make_server(hostname,\
port,\
server_class=WSGIServer,\
handler_class=WebSocketWSGIRequestHandler,\
app=WebSocketWSGIApplication(handler_cls=TestWebSocket)\
)
self.server.initialize_websockets_manager()
self.thread = threading.Thread(target=self.server.serve_forever)
self.thread.start()
print("Server started for {}:{}".format(hostname, str(port)))
def shutdown(self):
self.server.shutdown()
As explained here, redirecting the stdio/stdin is very simple with RPyC 2. This means that 'print' commands executed in the server, will display the printed string on the client side.
RPyC 2, as explained here, is un-secured and is not recommended, but I couldn't find anywhere how can I print on the client side with RPyC 3.
Does anyone know how to achieve this?
Edit:
For example, this is the code to my server:
import rpyc
import time
from rpyc.utils.server import ThreadedServer
class TimeService(rpyc.Service):
def exposed_print_time(self):
for i in xrange(10):
print time.ctime()
time.sleep(1)
if __name__ == "__main__":
t = ThreadedServer(TimeService, port=8000)
t.start()
and in my client, I run:
conn = rpyc.connect("192.168.1.5")
conn.root.print_time()
my goal is to get the time every second (or anything else I want to print) in the client's stdout, but the client just hangs and the time is only printed in the server.
you could use return on server side:
#on server
def exposed_test(self):
return "this is test"
#on client
conn.root.test()
>>> 'this is test'
from BaseHTTPServer import HTTPServer
from CGIHTTPServer import CGIHTTPRequestHandler
import socket,ssl
import time
import Config
class StartHTTPServer:
'''Web server to serve out map image and provide cgi'''
def __init__(self):
# Start HTTP Server. Port and address defined in Config.py
srvraddr = ("", Config.HTTP_PORT) # my hostname, portnumber
srvrobj = HTTPServer(srvraddr, CGIHTTPRequestHandler)
srvrobj.socket = ssl.wrap_socket(srvrobj.socket,server_side=True,
certfile="c:\users\shuen\desktop\servertryout 23022012\serverCert.crt",
keyfile="c:\users\shuen\desktop\servertryout 23022012\privateKey.key",
ssl_version=ssl.PROTOCOL_TLSv1,
do_handshake_on_connect=True)
print srvrobj.socket.cipher()
print srvrobj.socket.getsockname()
print "HTTP server running at IP Address %s port %s." % (Config.HTTP_ADDRESS, Config.HTTP_PORT)
srvrobj.serve_forever() # run as perpetual demon
srvrobj.socket.accept()
message='hello from server.<EOF>'
srvrobj.socket.send(message)
I have tried to send data with a normal socket, which works. However, the code i'm working on is using socketServer and can't be change. I cannot find any example which will send data across to the server. How can I do that?
If you really cannot change your server software, you must use a wrapper, e. g. openssl s_server.