I am learning the socketserver module and I am following the example but I modified the handle function a bit
class CustomServer(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print(f">{self.client_address[0]}: {self.data}")
def send(self, targets=[]):
if not targets:
return
if __name__ == "__main__":
HOST, PORT = "localhost", 6666
with socketserver.TCPServer((HOST, PORT), CustomServer) as server:
server.serve_forever()
Now when I try to use netcat and send sth to the server I don't see anything being outputted to the console
nc -v 10.0.0.112 6666
How do you properly edit the handle method so that it will print the address of the client each time
It is really important to understand the OOP concept and how to use it
Looking at the source code for socketserver I realized that I can create a class that inherits the BaseRequestHandler than I modified the handler method and passed my class to the TCPServer
class CustomHandler(BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print(f">{self.client_address[0]}: {self.data}")
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 6666
server = TCPServer(((HOST, PORT)), CustomHandler)
server.serve_forever()
Related
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'm completely lost trying to create a UDP server/client for my game in python. I'm new to the language and only have limited experience with networking. Right now, the server runs, but doesn't seem to be getting any messages from the client.
Server:
class GameServer:
class GameServerUDPHandler(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)
def __init__(self, port):
self.server = socketserver.UDPServer(("localhost", port), self.GameServerUDPHandler)
def start_server(self):
self.server.serve_forever(
Client:
import socket
import sys
class GameClient:
def __init__(self, port, host):
self.port = port
self.host = host
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def register(self):
self.socket.sendto(bytes("register\n", "utf-8"), (self.host, self.port))
self.numberID = int(self.socket.recv(1024))
print("Received: {}".format(self.numberID))
-Main/Start of program
import gameserver
import gameclient
if __name__ == "__main__":
server = gameserver.GameServer(1300)
server.start_server()
client = gameclient.GameClient(1300, "localhost")
client.register()
NOTE: I'm most likely to multiple things wrong and may be violating several best practices in the language. I really have no clue.
The problem is that some of these calls are blocking. In particular, the serve_forever() method will run forever, so you need to put that on a separate thread if you want the rest of your program to continue:
import threading
if __name__ == "__main__":
server = GameServer(1300)
server_thread = threading.Thread(target=lambda: server.start_server())
server_thread.start()
time.sleep(1) # Give it time to start up; not production quality code of course
client = GameClient(1300, "localhost")
client.register()
socket.recv() is also a blocking call but that might be okay in this case.
Seems like this library isn't asynchronous so your first call to serve_forever will not return and your client never gets started. You can create a new thread to launch the server on or split your client and server into seperate processes.
I've been playing around with Python's SocketServer:
#!/usr/bin/python
import SocketServer
class EchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
data=self.request.recv(1024)
self.request.send(data)
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), TCPEchoServer)
server.serve_forever()
From reading the source, I know that RequestHandler.__init__() receives request as a parameter and keeps a reference to it in self.request.
Where can I find the specifications for the request object?
In the documentation of RequestHandler.handle.
I've created a class for a server with the declaration:
class myServer(socketserver.BaseRequestHandler):
def handle(self):
pass
And started it with:
someServer = socketserver.UDPServer((HOST, PORT), myServer)
someServer.serve_forever()
My question is: how can I get the server to shutdown itself? I've seen it has a base class (of a base class) called BaseServer with a shutdown method. It can be called on someServer with someServer.shutdown() but this is from the outside of the server itself.
By using threads. Serving by one thread and going via another after your timeout.
Consider this working example. Modify it for your UDPServer
import threading
import time
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
def worker():
# minimal web server. serves files relative to the
print "serving at port", PORT
httpd.serve_forever()
def my_service():
time.sleep(3)
print "I am going down"
httpd.shutdown()
h = threading.Thread(name='httpd', target=worker)
t = threading.Thread(name='timer', target=my_service)
h.start()
t.start()
You could use twisted. Its about the best networking lib for python, here is an example of a UDP server here is (taken from the twisted documentation) the simplest UDP server ever written;
#!/usr/bin/env python
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
# Here's a UDP version of the simplest possible protocol
class EchoUDP(DatagramProtocol):
def datagramReceived(self, datagram, address):
self.transport.write(datagram, address)
def main():
reactor.listenUDP(8000, EchoUDP())
reactor.run()
if __name__ == '__main__':
main()
You can then close this down by calling self.transport.loseConnection() When you are ready or a specific event happens.
The server instance is available as self.server in the handler class. So you can call self.server.shutdown() in the handle method.
This is the code which i played, but each time i make a mistake i can't relaunch it.
It says to me that the port / socket is already used
That's the first question
The second one is in my MyTCPHandler how can i kno the port used ?
here is my code :
# MetaProject v 0.2
# -*- coding: utf-8 -*-
"""
Thanks to :
People from irc :
Flox,Luyt
People from stack Overflow :
Philippe Leybaert,Platinum Azure,methodin,Suresh Kumar,S.Lott,MatTheCat,
kevpie,Ignacio Vazquez-Abrams,adamk,Frédéric Hamidi,THC4k,THC4k,Blam
"""
import SocketServer
import threading
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024)
socket = self.request
print "%s wrote:" % self.client_address[0]
print self.data
print self.__dict__
socket.sendto(self.data.upper(), self.client_address)
def serve_thread(host, port):
server = SocketServer.TCPServer((host, port), MyTCPHandler)
server.serve_forever()
if __name__ == "__main__":
threading.Thread(target=serve_thread,args=('localhost', 1238)).start()
threading.Thread(target=serve_thread,args=('localhost', 1237)).start()
print "toto"
i've made :
def serve_thread(host, port):
if port == 1858 :
server = SocketServer.TCPServer((host, port), Serverhttp,bind_and_activate=True)
elif port == 1958 :
server = SocketServer.TCPServer((host, port), Serversmtp,bind_and_activate=True)
server.allow_reuse_address=True
server.serve_forever()
but it doesn't work.
Regards
It's actually easier than that -- you can just set it as a class variable, rather than overriding init. E.g.,
class MyServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True
Create your SocketServer with bind_and_activate=True in the call to the constructor.
Then set server.allow_reuse_address=True.
If you want to differentiate between the two ports, you can use two different classes for the request handlers.
Edit:
Modify your code to look like:
def serve_thread(host, port):
if port == 1858 :
server = SocketServer.TCPServer((host, port), Serverhttp,bind_and_activate=True)
elif port == 1958 :
server = SocketServer.TCPServer((host, port), Serversmtp,bind_and_activate=True)
server.allow_reuse_address=True
server.server_bind()
server.server_activate()
server.serve_forever()
It might be cleaner to create your own server class. Something like this:
class ReuseAddrServer(SocketServer.TCPServer):
def __init__(self, (host, port)):
SocketServer.TCPServer.__init__(self, (host, port), bind_and_activate=False)
self.allow_reuse_address = True
self.server_bind()
self.server_activate()