I tried many different options, even considered nodejs, but as for me this package is very cumbersome. I did not think of anything clever, how I installed the Tornado application for Python. I created how many servers I need to listen to the ports and redirect them to other ports, then using ajax requests I collected data from the ports. It seems pretty good and very simple:
#!/usr/bin/env python #coding=utf-8 import tornado.web import socket import os import errno from tornado.ioloop import IOLoop from tornado.platform.auto import set_close_exec class UDPServer1(object): def __init__(self, io_loop=None): self.io_loop = io_loop self._sockets = {} # fd -> socket object self._pending_sockets = [] self._started = False def add_sockets(self, sockets): if self.io_loop is None: self.io_loop = IOLoop.instance() for sock in sockets: self._sockets[sock.fileno()] = sock add_accept_handler(sock, self._on_recive, io_loop=self.io_loop) def bind(self, port, address=None, family=socket.AF_UNSPEC, backlog=25): sockets = bind_sockets(port, address=address, family=family, backlog=backlog) if self._started: self.add_sockets(sockets) else: self._pending_sockets.extend(sockets) def start(self, num_processes=1): assert not self._started self._started = True if num_processes != 1: process.fork_processes(num_processes) sockets = self._pending_sockets self._pending_sockets = [] self.add_sockets(sockets) def stop(self): for fd, sock in self._sockets.iteritems(): self.io_loop.remove_handler(fd) sock.close() def _on_recive(self, data, address): global w1 w1 = data # print (w1) def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=25): sockets = [] if address == "": address = None flags = socket.AI_PASSIVE if hasattr(socket, "AI_ADDRCONFIG"): flags |= socket.AI_ADDRCONFIG for res in set(socket.getaddrinfo(address, port, family, socket.SOCK_DGRAM, 0, flags)): af, socktype, proto, canonname, sockaddr = res sock = socket.socket(af, socktype, proto) set_close_exec(sock.fileno()) if os.name != 'nt': sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if af == socket.AF_INET6: if hasattr(socket, "IPPROTO_IPV6"): sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) sock.setblocking(0) sock.bind(sockaddr) sockets.append(sock) return sockets if hasattr(socket, 'AF_UNIX'): def bind_unix_socket(file, mode=0600, backlog=128): sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) set_close_exec(sock.fileno()) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) try: st = os.stat(file) except OSError, err: if err.errno != errno.ENOENT: raise else: if stat.S_ISSOCK(st.st_mode): os.remove(file) else: raise ValueError("File %s exists and is not a socket", file) sock.bind(file) os.chmod(file, mode) sock.listen(backlog) return sock def add_accept_handler(sock, callback, io_loop=None): if io_loop is None: io_loop = IOLoop.instance() def accept_handler(fd, events): while True: try: data, address = sock.recvfrom(2500) except socket.error, e: if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): return raise callback(data, address) io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ) ################################################################### #######UDP2############# class UDPServer2(object): def __init__(self, io_loop=None): self.io_loop = io_loop self._sockets = {} # fd -> socket object self._pending_sockets = [] self._started = False def add_sockets(self, sockets): if self.io_loop is None: self.io_loop = IOLoop.instance() for sock in sockets: self._sockets[sock.fileno()] = sock add_accept_handler(sock, self._on_recive, io_loop=self.io_loop) def bind(self, port, address=None, family=socket.AF_UNSPEC, backlog=25): sockets = bind_sockets(port, address=address, family=family, backlog=backlog) if self._started: self.add_sockets(sockets) else: self._pending_sockets.extend(sockets) def start(self, num_processes=1): assert not self._started self._started = True if num_processes != 1: process.fork_processes(num_processes) sockets = self._pending_sockets self._pending_sockets = [] self.add_sockets(sockets) def stop(self): for fd, sock in self._sockets.iteritems(): self.io_loop.remove_handler(fd) sock.close() def _on_recive(self, data, address): global w2 w2 = data # print (w) def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=25): sockets = [] if address == "": address = None flags = socket.AI_PASSIVE if hasattr(socket, "AI_ADDRCONFIG"): flags |= socket.AI_ADDRCONFIG for res in set(socket.getaddrinfo(address, port, family, socket.SOCK_DGRAM, 0, flags)): af, socktype, proto, canonname, sockaddr = res sock = socket.socket(af, socktype, proto) set_close_exec(sock.fileno()) if os.name != 'nt': sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if af == socket.AF_INET6: if hasattr(socket, "IPPROTO_IPV6"): sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) sock.setblocking(0) sock.bind(sockaddr) sockets.append(sock) return sockets if hasattr(socket, 'AF_UNIX'): def bind_unix_socket(file, mode=0600, backlog=128): sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) set_close_exec(sock.fileno()) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) try: st = os.stat(file) except OSError, err: if err.errno != errno.ENOENT: raise else: if stat.S_ISSOCK(st.st_mode): os.remove(file) else: raise ValueError("File %s exists and is not a socket", file) sock.bind(file) os.chmod(file, mode) sock.listen(backlog) return sock def add_accept_handler(sock, callback, io_loop=None): if io_loop is None: io_loop = IOLoop.instance() def accept_handler(fd, events): while True: try: data, address = sock.recvfrom(2500) except socket.error, e: if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): return raise callback(data, address) io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ) ############################################# #############WEB1########### class MainHandler(tornado.web.RequestHandler): def set_default_headers(self): self.set_header("Access-Control-Allow-Origin", "*") self.set_header("Access-Control-Allow-Headers", "x-requested-with") self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') def get(self): self.write(w1) def make_app(): return tornado.web.Application([ (r"/", MainHandler), ]) ################################# #############WEB2########### class MainHandler2(tornado.web.RequestHandler): def set_default_headers(self): self.set_header("Access-Control-Allow-Origin", "*") self.set_header("Access-Control-Allow-Headers", "x-requested-with") self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') def get(self): self.write(w2) def make_app2(): return tornado.web.Application([ (r"/", MainHandler2), ]) ################################# if __name__ == '__main__': serv1 = UDPServer1() serv1.bind(4001) serv1.start() serv2 = UDPServer2() serv2.bind(4002) serv2.start() app1 = make_app() app1.listen(8801) app2 = make_app2() app2.listen(8802) IOLoop.instance().start()
Here the script listens to two UDP ports 4001 and 4002 and redirects to ports 8801 and 8802, you can simply go to localhost: 8801 or, if from a remote computer, then IPadress: 8801 for example and see the accepted value on the UDP port of localhost: 4001. You can also see for yourself what came on UDP port 4002. You can access different machines at the same time on port 8801 and 8802, do not block anything and do not slow down ... You can also use ajax requests. At first, the problem of cross-domain queries arose, but here it was solved by adding headers to the response of the server. In this script, this problem is solved. I don’t know if you can do this or not, but I just found the necessary script and redid it for myself. It seems to work. The script needs to be placed in the server autoload, so that after the reboot everything starts automatically and works. If I contact the server before the UDP packet arrives, the server returns error 500, I don’t know how to remove it, but it doesn’t affect my system, the ajax request does not return anything, until I receive data on the UDP port.