Using Pyro4 I haven't managed to successfully execute a callback from server to client.
The server script looks as follows:
class RobotController(object):
def __init__(self):
self.robotStates = []
def moveDemo(self, motionTime):
stopTime = datetime.datetime.now() + datetime.timedelta(0,motionTime)
while datetime.datetime.now() < stopTime:
print "Robot is moving..."
time.sleep(1)
print "Robot stopped"
return 0
def doCallback(self, callback):
print("server: doing callback 1 to client")
try:
callback.call1()
except:
print("got an exception from the callback.")
print("".join(Pyro4.util.getPyroTraceback()))
print("server: doing callback 2 to client")
try:
callback.call2()
except:
print("got an exception from the callback.")
print("".join(Pyro4.util.getPyroTraceback()))
print("server: callbacks done")
if __name__ == '__main__':
robotController = RobotController()
if os.name == 'posix':
daemon = Pyro4.Daemon(host="192.168.1.104", port=8000);
else:
daemon = Pyro4.Daemon(host="localhost", port=8000);
Pyro4.Daemon.serveSimple(
{ robotController: "robotController"},
ns=False,
daemon=daemon,
verbose = True
)
and the client looks as follows:
class CallbackHandler(object):
def crash(self):
a=1
b=0
return a//b
def call1(self):
print("callback 1 received from server!")
print("going to crash - you won't see the exception here, only on the server")
return self.crash()
#Pyro4.callback
def call2(self):
print("callback 2 received from server!")
print("going to crash - but you will see the exception here too")
return self.crash()
daemon = Pyro4.core.Daemon()
callback = CallbackHandler()
daemon.register(callback)
#robotController = Pyro4.Proxy("PYRO:robotController#192.168.1.104:8000")
robotController = Pyro4.Proxy("PYRO:robotController#localhost:8000")
robotController._pyroOneway.add("doCallback")
robotController.doCallback(callback)
When executing the command robotController.doCallback(callback), the method doCallback on server is executed, but the server cannot access the client. It returns the following:
Traceback (most recent call last):
File "C:\LASTNO\Python Projects\PiBot\RobotServer\PyroServer\pyroServer.py", line 63, in doCallback
callback.call2()
File "C:\Python27\lib\site-packages\Pyro4\core.py", line 160, in __call__
return self.__send(self.__name, args, kwargs)
File "C:\Python27\lib\site-packages\Pyro4\core.py", line 286, in _pyroInvoke
self.__pyroCreateConnection()
File "C:\Python27\lib\site-packages\Pyro4\core.py", line 371, in __pyroCreateConnection
raise ce
CommunicationError: cannot connect: [Errno 10061] No connection could be made because the target machine actively refused it
Does anyone know what could be the cause of the error and how to fix it? Thank you!
I solved the problem by modifying the client code as follows:
class CallbackHandler(object):
def crash(self):
a=1
b=0
return a//b
def call1(self):
print("callback 1 received from server!")
print("going to crash - you won't see the exception here, only on the server")
return self.crash()
#Pyro4.callback
def call2(self):
print("callback 2 received from server!")
print("going to crash - but you will see the exception here too")
return self.crash()
daemon = Pyro4.core.Daemon()
callback = CallbackHandler()
daemon.register(callback)
with Pyro4.core.Proxy("PYRO:robotController#localhost:8000") as server:
server._pyroOneway.add("doCallback")
server.doCallback(callback)
motion = server.moveDemo(15)
print("waiting for callbacks to arrive...")
print("(ctrl-c/break the program once it's done)\n")
daemon.requestLoop()
Related
I'm currently creating an encrypted chat program. Text chat works well. However, I want to implement file transfer, but it doesn't work. My code is trying to work in a way that when one client tries to transfer a file, the server receives it and sends it to another client. When I type '/filetransfer' to transfer file.
Dick: hi
/filetransfer
Sending...
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Python\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "c:\Users\USER\Desktop\filetest\client.py", line 198, in sndChat
self.sndFile()
File "c:\Users\USER\Desktop\filetest\client.py", line 233, in sndFile
clientSocket.send(l)
This error occurred. I think the client cannot send the file data.
Also, I would like to apply Diffie-Hellman and AES used for text encryption to file transfer. I spent a lot of time here, but it doesn't work. I desperately need help...
Client.py
def rcvChat(self):
print("\nWelcome to Chatee!")
while True:
try:
message = clientSocket.recv(4096).decode(encodeType)
if self.thred_done:
message=self.aes.decrypt(message)
print(message)
if message == 'filetransfer start':
filereceive_thread = threading.Thread(target=self.rcvChat)
filereceive_thread.join()
#write_thread = threading.Thread(target=self.sndChat)
#write_thread.join()
#self.rcvFile()
break
def sndChat(self):
while True:
message = input('')
if message == '/filetransfer':
message = self.aes.encrypt(message)
clientSocket.send(message)
writefile_thread = threading.Thread(target=self.sndChat)
writefile_thread.start()
self.sndFile()
break
message = self.aes.encrypt(message)
clientSocket.send(message)
def sndFile(self):
print("---File Transfer---")
print("Type a file name...")
filename = 'C:\\Users\\USER\\Desktop\\filetest\\test.txt'
#clientSocket.send(filename.encode(encodeType))
#data_transferred = 0
if not exists(filename):
print("The file doesn't exsit.")
f = open(filename,'rb')
print ('Sending...')
l = f.read(8096)
while (l):
print ('Sending...')
#data_transferred += clientSocket.send(l)
clientSocket.send(l)
l = f.read(8096)
f.close()
print ('Done Sending')
#clientSocket.shutdown(socket.SHUT_WR)
print (clientSocket.recv(8096))
#clientSocket.close
def rcvFile(self):
#filename = clientSocket.recv(1024).decode(encodeType)
#filename = self.aes.decrypt(filename)
filename = 'received.txt'
f = open(filename,'wb')
while True:
print ('Receiving...')
l = clientSocket.recv(8096)
if not l:
print("Fail file transfer")
#sys.exit()
while (l):
print ('Receiving...')
f.write(l)
l = clientSocket.recv(8096)
f.close()
print ('Done Receiving')
Server.py
def handle_client(self,client,client_addr):
client_pvt_key=self.client_keys[client]
client_name=self.clients[client]
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}] - Connected")
print(f"Active Connections - {threading.active_count()-1}")
self.broadcast(f'{client_name} has joined the chat!\n\n')
aes=AESCipher(client_pvt_key)
while True:
try:
msg = aes.decrypt(client.recv(self.header)) #복호화 안하고 바로 브로드캐스트 해도 될듯
if msg == '/filetransfer':
#보낸 사람 제외하고 보내기
self.broadcast('filetransfer start')
thread = threading.Thread(target=self.sndFile, args=(client, ))
thread.start()
thread.join()
elif msg==self.quit_msg:
break
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}]")
msg=f'{client_name}: {msg}'
self.broadcast(msg)
except:
break
client.close()
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}] - quit_msged")
del self.clients[client]
del self.client_keys[client]
self.broadcast(f'{client_name} has left the chat\n')
print(f"Active Connections - {threading.active_count()-2}")
def broadcast(self,msg):
for client in self.clients:
aes=AESCipher(self.client_keys[client])
crypted_msg=aes.encrypt(msg)
client.send(crypted_msg)
def sndFile(self, client):
print("---File Transfer---")
#print("Type a file name...")
client_pvt_key=self.client_keys[client]
aes=AESCipher(client_pvt_key)
#filename = client.recv(1024).decode(self.encodetype)
#self.broadcast('fuck',filename)
while True:
try:
l = client.recv(8096)
print('Rceiving...')
#del self.clients[client]
for client in self.clients:
client.send(l)
#client.send(filename.encode(self.encodetype))
#l = client.recv(8096)
if not l:
print("Fail file transfer")
except:
print('file fail')
break
I'm trying to write a test http-server for a personal IoT project I"ve got going. My project has its own web-server that responds to certain 'page load' requests. Now I'm trying to expand the web-page itself. Now I could develop the actual server itself simultaneously but downloading it to the IoT device every iteration is extraordinarily slow so I've decided to write a test-server on my machine instead.
The test-server is written in python. The code below is the test-server in its entirety:
import http.server
import socketserver
import string
PORT = 8000
class MyHandler(http.server.SimpleHTTPRequestHandler):
def __init__(self):
self.pageFuncs = { "/Lights": self.doLightsPage,
"/Show": self.doShowPage,
"/Static": self.doShowTypePage,
"/Effects": self.doShowTypePage,
"/Playlist": self.doShowTypePage,
"/Select": self.doControlTypePage,
"/Controls": self.doControlTypePage,
"/query": self.doQueryResultsPage }
self.STATIC_SHOW_TYPE = 0
self.EFFECTS_SHOW_TYPE = 1
self.PLAYLIST_SHOW_TYPE = 2
self.SELECT_CTRL_TYPE = 0
self.CONTROL_CTRL_TYPE = 1
self.LightsOn = 0
self.LightShowOn = 0
self.showType = STATIC_SHOW_TYPE
self.ctrlType = SELECT_CTRL_TYPE
def do_GET(self):
try:
page_name = self.path
if (page_name in pageFuncs):
print (page_name)
self.send_response(200)
self.send_header("Content-type", "text/json")
self.end_headers()
self.pageFuncs[page_name](self)
return
else:
super().do_GET()
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
except :
pass
def doLightsPage(self):
self.bLightsOn ^= 1
return doQueryResultsPage()
def doShowPage(self):
self.bLightShowOn ^= 1
return doQueryResultsPage()
def doShowTypePage(self):
if (self.path == '/Static') :
self.showType = STATIC_SHOW_TYPE
elif (self.path == '/Effects') :
self.showType = EFFECTS_SHOW_TYPE
else :
self.showType = PLAYLIST_SHOW_TYPE
return doQueryResultsPage()
def doControlTypePage(self):
if (self.path == '/Select') :
self.ctrlType = SELECT_CTRL_TYPE
else :
self.ctrlType = CONTROL_CTRL_TYPE
return doQueryResultsPage()
def doQueryResultsPage(self):
json_data = '{ \"power\": {}, \"show\": {},'
json_data += '\"show_type\": {}, \"control_type\": {} }'
json_data = format(json_data, bLightsOn, bLightShowOn, showType, ctrlType);
self.write(json_data)
def main():
try:
server = socketserver.TCPServer(("", PORT), MyHandler)
print ('started httpserver...')
server.serve_forever()
except KeyboardInterrupt:
print ('^C received, shutting down server')
server.socket.close()
if __name__ == '__main__':
main()
The point of the test is to receive a valid request; change a value and return a json string back reflecting the internal state of the server.
However, as soon as I try to load any of the pages, I get the following error message:
Exception happened during processing of request from ('127.0.0.1', 50149)
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0\lib\socketserver.py", line 316, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0\lib\socketserver.py", line 347, in process_request
self.finish_request(request, client_address)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0\lib\socketserver.py", line 360, in finish_request
self.RequestHandlerClass(request, client_address, self)
TypeError: __init__() takes 0 positional arguments but 4 were given
So my question is, what am I doing wrong?
I've taken the code format from the following stackoverflow topic which appears to be trying to do the same things, maybe I'm misunderstanding something?
I am running a web server on a raspberry pi which is logging temperatures etc.
I am using websockets in Tornado to communicate with my client.
I want the client to be able to control when the server is sending data over the socket.
My thought was that when client connects and says it's ready, the server will start a loop where it logs temps every second. But I need this loop to run asynchronously. This is where I get in trouble. I tried to follow an example, but I cant get it to run properly.
class TemperatureSocketHandler(tornado.websocket.WebSocketHandler):
#gen.coroutine
def async_func(self):
num = 0
while(self.sending):
num = num + 1
temp = self.sense.get_temperature()
yield self.write_message(str(temp))
gen.sleep(1)
def open(self):
print("Temperature socket opened")
self.sense = SenseHat()
self.sense.clear()
self.sending = False
def on_message(self, message):
if(message == "START"):
self.sending = True
if(message == "STOP"):
self.sending = False
tornado.ioloop.IOLoop.current().spawn_callback(self.async_func(self))
But I get an error here when I run this:
ERROR:tornado.application:Exception in callback functools.partial(<function wrap.<locals>.null_wrapper at 0x75159858>)
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.5/site-packages/tornado/ioloop.py", line 605, in _run_callback
ret = callback()
File "/home/pi/.local/lib/python3.5/site-packages/tornado/stack_context.py", line 277, in null_wrapper
return fn(*args, **kwargs)
TypeError: 'Future' object is not callable
You have to use IOLoop.add_future()
since async_func() returns a Future (it is decorated as a coroutine!).
Also, you should add the future, when you receive the start message, not on any message:
def on_message(self, message):
if(message == "START"):
self.sending = True
tornado.ioloop.IOLoop.current().add_future(
self.async_func(self), lambda f: self.close())
if(message == "STOP"):
self.sending = False
I try to make a chat on Python3. Here is my code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = sock.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
sock.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message())
send_message_thread = threading.Thread(target=send_message())
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
run()
sock.close()
But after the execution and sending a message from other client I get an error message:
Server starts working
Traceback (most recent call last):
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 40, in <module>
run()
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 30, in run
get_message_thread = threading.Thread(target=get_message())
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 15, in get_message
data = sock.recv(1024).decode()
OSError: [Errno 107] Transport endpoint is not connected
Process finished with exit code 1
I've read, that there are some troubles with sock.accept(), but everything's alright here, as I think.
Your program has many flaws. As zondo mentioned, you are incorrectly passing the target. They should be like threading.Thread(target=get_message). Second problem is, you should use conn (and not sock) for sending and receiving data. Third problem is, main thread was blocking at accept call and will wait for the connection. But soon as it accepts a connection, it will exit. From the main thread, you should wait for get_message_thread and send_message_thread. Try the modified code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = conn.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
conn.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message)
send_message_thread = threading.Thread(target=send_message)
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
get_message_thread.join()
send_message_thread.join()
run()
sock.close()
I've seen and read a lot about this particular issue on the internet.
I am writing a simple chat server and client using socket in python for learning purpose mainly.
I've observed an issue here.
Here is my server code :
__author__ = 'pchakraverti'
import socket
import select
import sys
class NickSocketMap(object):
count = 0
def __init__(self, nick, client_socket):
self.nick = nick
self.client_socket = client_socket
NickSocketMap.count += 1
#staticmethod
def display_count():
print "Total number of clients is %d" % NickSocketMap.count
host = ""
port = 7575
socket_list = []
nick_list = []
cnt = 0
recv_buffer = 1024
def register_nick(nick, client_socket):
obj = NickSocketMap(nick, client_socket)
nick_list.append(obj)
def process_request(request_string, client_socket):
parts = request_string.split("|")
if parts[0] == "set_nick":
register_nick(parts[1], client_socket)
client_socket.send("nick_set")
elif parts[0] == "transmit_msg":
broadcast_message(parts[1], parts[2])
return 1
def broadcast_message(message, client_nick):
for s in nick_list:
if s.nick == client_nick:
try:
s.client_socket.send(message)
except socket.errno, ex:
print ex
break
def run_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.bind((host, port))
except socket.errno, ex:
print ex
sys.exit(-1)
sock.listen(10)
# add the parent socket in the list
socket_list.append(sock)
# keep the server alive
while True:
try:
read_ready, write_ready, in_error = select.select(socket_list, [], [], 0)
except select.error, ex:
print ex
continue
for s in read_ready:
# check if s is the parent socket
if s == sock:
# accept new connection and append to list
try:
con, addr = s.accept()
if con not in socket_list:
socket_list.append(con)
except socket.errno, ex:
print ex
else:
try:
# receive packet from connected client
packet = s.recv(recv_buffer)
if not packet:
socket_list.remove(s)
read_ready.remove(s)
for n in nick_list:
if n.client_socket == s:
nick_list.remove(n)
break
break
print packet
except socket.errno, ex:
print ex
continue
process_request(packet, s)
sock.close()
if __name__ == "__main__":
run_server()
and here is my client code:
__author__ = 'pchakraverti'
import socket
nick = ""
host = "192.168.0.167"
port = 7575
sock = ""
def welcome():
print "Welecome to SecuChat!"
print "---------------------"
def init():
nick = raw_input("Enter your chat nickname : ")
print nick
global sock
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
except socket.errno, ex:
print ex
sock.send("set_nick|"+nick)
#sock.close()
if __name__ == "__main__":
welcome()
init()
In the client code, when I don't do the sock.close(), the server runs into an exception :
Traceback (most recent call last):
File "server.py", line 102, in <module>
run_server()
File "server.py", line 84, in run_server
packet = s.recv(recv_buffer)
socket.error: [Errno 104] Connection reset by peer
how ever, when I add that line, the problem doesn't occur.
Now I've two questions :
i) I've handled exceptions in the server.py, why is this exception not being handled and why is it crashing the code ? How can I make the server more robust and what am I missing ?
ii) What is the logic behind this crash and exception in relation to the sock.close() line in the client ?
i) Your try-except block doesn't catch any exceptions.
The first argument to except must be the type of the exception you want to catch. socket.errno is not an exception class but a module. You need to catch socket.error:
except socket.error, ex:
print ex
It "crashes" your code because any exception that isn't handled somewhere in the call stack propagates outwards until it hits an except. If there is no handler the program is terminated.
ii) When the client terminates without closing the connection, a RST packet is sent by the TCP/IP stack of your OS. This is roughly the equivalent of hanging up a phone without saying goodbye. Python converts this into an exception with the text "Connection reset by peer". It simply means that since you called read() Python assumed you expect to receive something and when the connection suddenly disconnected, Python informs you of this by raising the exception.