I am trying to make a server that allows TCP, UDP and HTTP connections by making each process have its own thread. I already accomplished TCP and HTTP connections, and the UDP portion starts up correctly, but when I try to send a message via UDP, the system hangs. Does anyone know how to fix this problem?
The UDP Class Handler:
class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print("{} wrote: ".format(self.client_address[0]))
print(data)
socket.sendto(data.upper(), self.client_address)
The UDP Thread:
class ThreadedUDPServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
pass
Location in code:
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "127.0.0.1", 8000
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
http_thread = threading.Thread(target=httpd.serve_forever)
print("Website serving at port", PORT)
udpserver = ThreadedUDPServer((HOST,PORT+1), ThreadedUDPRequestHandler)
udp_thread = threading.Thread(target=udpserver.serve_forever)
print("UDP serving at port", PORT+1)
tcpserver = ThreadedTCPServer((HOST, PORT-1), ThreadedTCPRequestHandler)
server_thread = threading.Thread(target=tcpserver.serve_forever)
print("TCP serving at port", PORT-1)
udp_thread.start()
Solved:
I forgot to add
udp_thread.start()
I forgot to add
udp_thread.start()
at the bottom
Related
I'm trying to send data to a python server:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',6000))
s.listen(5)
while True:
clientsocket,address = s.accept()
print(f"Got connection from {address} !")
from godot:
var socket = PacketPeerUDP.new()
socket.set_dest_address("127.0.0.1",6000)
socket.put_packet("quit".to_ascii())
based on this link
but it doesn't seem to be working, How do I send the data?
i'm not that familiar with python servers, but it looks like you have a python server that listens for TCP connections but in godot you connect via UDP Client.
As seen in this Answer SOCK_STREAM is for TCP Server and SOCK_DGRAM for UDP.
I am not sure which of those you want to use. An example server for UDP would be:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(('127.0.0.1',6000))
bufferSize = 1024
#s.listen(5)
print("running")
while True:
bytesAddressPair = s.recvfrom(bufferSize)
message = bytesAddressPair[0]
clientMsg = "Message from Client:{}".format(message)
print(clientMsg)
I copied most of it from here : Sample UDP Server
If you wanted to have a TCP Server you should alter the Godot part to use a TCP Client. See the official docs here
figured it out thanks to #René Kling 's answer
just incase someone wants the complete version
python server:
import socket
HOST = "127.0.0.1"
PORT = 6000
s= socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind((HOST, PORT))
while True:
message, addr = s.recvfrom(1024)
print(f"Connected by {addr}")
Godot:
extends Node2D
tool
export(bool) var btn =false setget set_btn
var socket = PacketPeerUDP.new()
func set_btn(new_val):
socket.set_dest_address("127.0.0.1", 6000)
socket.put_packet("Time to stop".to_ascii())
I'm trying to send a message from a computer to a another computer that is not connected to the other computer local network.
I did port forwarding (port 8080, TCP) and I didn't manage to get the remote computer to connect and to send the message.
when i try to connect it's just getting stuck on the connect method (client).
I also need to mention that I'm open to change anything in the router settings.
the client code (remote computer):
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("%My public IP address%", 8080))
msg = s.recv(1024)
msg = msg.decode("utf-8")
print(msg)
the server code:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("192.168.0.2", 8080))
s.listen(5)
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.")
clientsocket.send(bytes("Hey there!!", "utf-8"))
clientsocket.close()
From my understanding, your aim is to connect to a server from a remote computer and send a message from the server to the client. As such, all it requires is the client to connect to the external-facing IP address of your server. Once that is done, router simply forwards the traffic according to the port forwarding rules.
Server:
import socket
def Main():
host = '10.0.0.140'
port = 42424
s = socket.socket()
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
while True:
data = c.recv(1024)
if not data:
break
data = str(data).upper()
c.send(data)
c.close()
if __name__ == '__main__':
Main()
Client:
import socket
def Main():
host = '10.0.0.140' #The host on your client needs to be the external-facing IP address of your router. Obtain it from here https://www.whatismyip.com/
port = 42424
s = socket.socket()
s.connect((host,port))
message = raw_input("->")
while message != 'q':
s.send(message)
data = s.recv(1024)
message = raw_input("->")
s.close()
if __name__ == '__main__':
Main()
Also do note that, When connecting to a server behind a NAT firewall/router, in addition to port forwarding, the client should be directed to the IP address of the router. As far as the client is concerned, the IP address of the router is the server. The router simply forwards the traffic according to the port forwarding rules.
I started a simple server that connects to a client, it worked a month ago but now it doesn't.
main
def main():
(client_socket, client_address) = start_server(('0.0.0.0', 8200))
print("online")
menu = """
enter the mode wanted out of:
write,
random,
cal,
file,
close to terminate connection"""
menu = menu.encode()
main_menu(client_socket, menu)
client_socket.close()
server_socket.close()
if __name__ == '__main__':
main()
start_server function
def start_server(addr):
global server_socket
server_socket = socket.socket()
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(addr)
server_socket.listen(1)
(client_socket, client_address) = server_socket.accept()
return client_socket, client_address
The server doesnt run the server_socket.accept() and i get this error for the client :
OSError: [WinError 10049] The requested address is not valid in its context
client socket
my_socket = socket.socket() # creates the socket
my_socket.connect(('0.0.0.0', 8200)) # connects to the server
choose_mode(my_socket) # main menu
why does it not accept the client?
I bound 0.0.0.0 and 8200 but connected to 127.0.0.1.
server
(client_socket, client_address) = start_server(('0.0.0.0', 8200))
client
my_socket.connect(('127.0.0.1', 8200)) # connects to the server
As I was explained:
because 0.0.0.0 isn't a target address to connect to, and binding to 127.0.0.1 is generally too restrictive
I assume you're trying to start a server in your localhost. Depending on the platform/ OS this code is running on, this address can be invalid . Perhaps this is what has changed, your underlying platform.
To avoid the issue , use
start_server((socket.gethostname(), 8200))
or
start_server(('127.0.0.1', 8200))
You can read more about using 0.0.0.0 below.
https://www.howtogeek.com/225487/what-is-the-difference-between-127.0.0.1-and-0.0.0.0/
I need to use socketserver to build a tcp server. According to their document, I need to inherit the class TCPServer, and pass it a subclass of class BaseRequestHandler where I rewrite the method handle().
Right now I need to build two server on different port, is there a way that in handle() function, (otherwise I have to setup two almost identical handler class, which is not I want), I can get my own port number?
Don't do it in the handle() method, pass the port number in (from this https://docs.python.org/2/library/socketserver.html#socketserver-tcpserver-example):
#!/usr/bin/env python
import SocketServer, argparse
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.server.server_address is a tuple (IP, port) the server is listening on
(host, port) = self.server.server_address
print 'port # is: {}'.format(port)
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--port', required=True, help='the TCP port to listen on')
args = parser.parse_args()
HOST, PORT = "localhost", int(args.port)
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
In this example, you must provide the port number as an argument when you start the program using the -p command line switch.
I just found out a solution might be eligible, but it's still not good enough since I still have to change two port in the code to make this work:
import socket
import threading
import SocketServer
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
port = None
def handle(self):
while True:
data = self.request.recv(1024)
if not data:
break
print self.port,data
class ThreadedTCPRequestHandler1(ThreadedTCPRequestHandler):
port = 9999
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler1)
ip, port = server.server_address
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
#print "Server loop running in thread:", server_thread.name
try:
while True:
continue
finally:
print 'quitting server'
server.shutdown()
server.server_close()
I would like to listen on 2 different UDP port with the same server.
I use SocketServer lib for my server, and basicly it looks like that;
SocketServer.UDPServer(('', 7878),CLASSNAME)
I would like to listen on 7878 and 7879 with the same server and same file.
Is that possible? If yes how?
Sure you can, using threads. Here's a server:
import SocketServer
import threading
class MyUDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print "%s wrote:" % self.client_address[0]
print data
socket.sendto(data.upper(), self.client_address)
def serve_thread(host, port):
server = SocketServer.UDPServer((host, port), MyUDPHandler)
server.serve_forever()
threading.Thread(target=serve_thread,args=('localhost', 9999)).start()
threading.Thread(target=serve_thread,args=('localhost', 12345)).start()
It creates a server to listen on 9999 and another to listen on 12345.
Here's a sample client you can use for testing this:
import socket
import sys
HOST, PORT = "localhost", 12345
data = 'da bomb'
# SOCK_DGRAM is the socket type to use for UDP sockets
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# As you can see, there is no connect() call; UDP has no connections.
# Instead, data is directly sent to the recipient via sendto().
sock.sendto(data + "\n", (HOST, PORT))
received = sock.recv(1024)
print "Sent: %s" % data
print "Received: %s" % received
Note: this was taken from the docs of the SocketServer module, and modified with threads.
Nope. Consider using Twisted.
No need to use threads for something like this. Consider http://code.google.com/p/pyev/