How to restart a TCP socketserver? - python

I have written a code for handling multiple requests at a time but my server freezes randomly after a while, is there any way to check and restart the server if there is no activity.
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
#doing some work and generating response
self.request.sendall(response)
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 4879
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.socket.close()

via bash if you want to stop the server ps aux|grep The name of the program|awk '{print $2}'|xargs kill

Related

Cannot connect to multi-threaded TCP server

I'm trying to setup a threaded server where multiple clients can connect at the same time. This is a bit long, please do bear with me. I've already read this helpful realpython article on sockets as well as the socket and socketserver docs.
Python provides facilities to create a server and the socketserver documentation even shows us:
import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print("Server loop running in thread:", server_thread.name)
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()
This works fine on my machine but what I'd like to de-couple the client implementation from the server. So I split the implementations and I have.
server.py:
import socketserver
import threading
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def main():
HOST, PORT = "localhost", 8080 # localhost aka 127.0.0.1
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = False # Do not stop and keep serving
server_thread.start()
print("Server loop running in thread: ", server_thread.name)
if __name__ == '__main__':
main()
and client.py
import socket
class Client:
def __init__(self, ip, port):
self.ip = ip
self.port = port
def start(self, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((self.ip, self.port))
sock.sendall(bytes(message, "ascii"))
response = str(sock.recv(1024), "ascii")
print("Received: {}".format(response))
def main():
client = Client("localhost", 8080)
client.start("Hello World!")
if __name__ == '__main__':
main()
Then I open two different shell occurences and I do:
$ python3 -m server
The server outputs its message and the shell hangs, which is the expected behavior since I turned daemon mode off and it is supposed to serve forever.
Pinging localhost works fine, all packages are received with no loss. On the other hand, using netstat, I can't seem to find the port I'm opening (8080).
and in the other:
$ python3 -m client
Fails with a ConnectionRefusedError which is the typical error when there is nothing to connect to.
My conclusion for now is that the server is closing the port at some point, I suppose when the main thread dies?
I'm not sure how to fix it though? What's wrong with the current implementation.
Thanks for the help.

How to make the run server methos thread safe?

I am using the "run" method in python that is running the web server.
I want to make it thread safe by using mutex.
How can i do this and where should i locate the mutex?
Thanks.
def run(serverClass=FlsLdkServiceThreadedHttpServer, handlerClass=FlsLdkServiceRequestHandler, hostName="localhost", port=1111):
serverAddress = (hostName, int(port))
httpd = serverClass(serverAddress, handlerClass)
logging.info("start")
if sConfigIsSecure == "Yes":
httpd.socket = ssl.wrap_socket(httpd.socket, certfile=sConfigCert, keyfile=sConfigPrivKey, server_side=True)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
logging.info('Stop')

A simple socket server and client program using python

SocketServer Program
This code is in raspberry:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The request handler 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.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)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# 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()
Socket Client Program
This code is in my laptop:
import socket
import sys
HOST, PORT = "192.168.1.40", 3360
data='Hello'
#data = data.join(sys.argv[1:])
# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(data + "\n")
# Receive data from the server and shut down
received = sock.recv(1024)
finally:
sock.close()
print "Sent: {}".format(data)
print "Received: {}".format(received)
Here the data sent should be received to server and sent back to client.
This is the error:
[Errno 10061] No connection could be made because the target machine actively refused it.
Try changing to HOST, PORT = "0.0.0.0", 9999 in the server. Now the server should listen on all interfaces and not just the loopback interface. The same could also be achieved using an empty string i.e HOST, PORT = "", 9999.

Connections outlive SocketServer.TCPServer?

How can I make a TCP server properly close sockets?
I wrote a simple TCP server to echo some information back to client. Now I would like to use it on localhost:8088 and stop it using killall and restart at any time as I'm working on the code.
However, I'm having trouble making it close all sockets and "free" the address, so when I quickly make a few tests, fix something in the code and then stop (Ctrl+C) and start the server again, I get socket.error: [Errno 98] Address already in use.
When I sudo netstat -ntap, I can still see few 127.0.0.1:8088 sockets in TIME_WAIT state. So I have to wait until they "die out".
My test case:
#!/usr/bin/python
import SocketServer
class MyEchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
# do something smart with the data, but for now, just say hello.
self.reply = "Content-Type: text/plain\r\n\r\nhello."
self.request.send(self.reply)
self.request.close()
def main():
server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler)
server.serve_forever()
if __name__ == '__main__':
HOST, PORT = "localhost", 8088
main()
What am I doing wrong? Shouldn't self.request.close() be enough?
I'm trying this on Debian with Python 2.7.3, although I need to support Squeeze with Python 2.6 as well.
The TCP stack puts the port into timed-wait for awhile (something like 30 seconds to multiple minutes depending on your system). You can change that behavior with the SO_REUSEADDR socket option. The trick is that the option must be set before the port is bound.
If you have the raw socket, you can:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SocketServer lets you set the option globally with the allow_reuse_address attribute:
SocketServer.TCPServer.allow_reuse_address = True
Or you can do it when you create the server:
def main():
server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler, False)
server.allow_reuse_address = True
server.server_bind()
server.serve_forever()
Or even override the bind method:
class MyTCPServer(SocketServer.TCPServer):
def server_bind(self):
self.allow_reuse_address = True
super(MyTCPServer, self).server_bind()
Here are 3 solutions that worked for me on my Windows machine.
(1) set globally
#!/usr/bin/python
import SocketServer
import time
SocketServer.allow_reuse_address = True
class MyEchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
# do something smart with the data, but for now, just say hello.
self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
self.request.send(self.reply)
self.request.close()
def main():
server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler)
server.serve_forever()
if __name__ == '__main__':
HOST, PORT = "localhost", 8088
main()
(2) Set locally
#!/usr/bin/python
import SocketServer
import time
class MyEchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
# do something smart with the data, but for now, just say hello.
self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
self.request.send(self.reply)
self.request.close()
def main():
server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler, False)
server.allow_reuse_address = True
server.server_bind()
server.server_activate()
server.serve_forever()
if __name__ == '__main__':
HOST, PORT = "localhost", 8088
main()
(3) Inherit
#!/usr/bin/python
import SocketServer
import time
class MyEchoHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
# do something smart with the data, but for now, just say hello.
self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
self.request.send(self.reply)
self.request.close()
class MyTCPServer(SocketServer.TCPServer):
def server_bind(self):
self.allow_reuse_address = True
SocketServer.TCPServer.server_bind(self)
def main():
server = MyTCPServer((HOST, PORT), MyEchoHandler)
server.serve_forever()
if __name__ == '__main__':
HOST, PORT = "localhost", 8088
main()
You can call server.shutdown() but you have to do it from another thread 8-( IMO this is weak area in Python's TCPServer.

Python multiple threaded servers running in the same program

So I am currently writing a python server for a small game. I am currently trying to have the program run two servers in threads. From testing I have found a small bump in my process and that is that only one server is running at a time. I am using different ports for each of the servers however the one connected first takes dominance.
Server code snippets:
class loginServer(socketserver.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
sent = str(self.data,'ascii').split(":")
print("login:\t\t",sent)
if (sent[0] == "l"):
#login check
#cur.execute("SELECT password, userid FROM `prototb` WHERE username = '"+sent[1]+"'")
cur.execute("SELECT `displayname`,`curmap`,`curpos`,`Inventory`,`abilities`,`password`,`userid` FROM `prototb` WHERE username = '"+sent[1]+"'")
plyInfo = cur.fetchone()#get the information from the database
if (plyInfo != None):#if the account doesnt exist the username is wrong
if (plyInfo[5] == sent[2]):#check the correctness of the password
print("Login-Success:\t",plyInfo)
send = pickle.dumps([plyInfo[1],plyInfo[2],plyInfo[3],plyInfo[4],plyInfo[5]])
else:
self.request.send(bytes("-", 'ascii'))#refuse entry (bad password)
else:
self.request.send(bytes("-", 'ascii'))#refuse entry (bad username)
def run_loginServer():
HOST, PORT = "localhost", 9000
# Create the server, binding to localhost on port 9000
server = socketserver.TCPServer((HOST, PORT), loginServer)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
And for the other server thread:
class podListener(socketserver.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
sent = str(self.data,'ascii').split(":")
print("pods:\t\t",sent)
if (sent[0] == "l"):
maps[mapNum][0] = sent[1]
maps[mapNum][1] = self.client_address[0]
maps[mapNum][2] = sent[2]
print("Pod Connected:\t",maps[mapNum])
#send confirmation
self.request.send(bytes("+", 'ascii'))
else:
print("Pod Failed connection: ", self.client_address[0])
def run_podListener():
HOST, PORT = "localhost", 9001
# Create the server, binding to localhost on port 9001
server = socketserver.TCPServer((HOST, PORT), podListener)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
Then I run this to start them both:
if __name__ == "__main__":
#get the database handle
run_dbConnect()
#run the map pod server
run_podLauncher()
#run the login server ### localhost 9000
run_loginServer()
The client works connecting to them separately, when I comment out the threads individually, but never together. Any help will be greatly appreciated.

Categories