How to remove the socket server from "busy" state after `kill PID`? - python

I have a simple socket server set-up to send some numbers to a client in the intranet. While testing, I stop the server.py script from terminal(CTRL+C) which later causes busy server error in Safari when I try to reach the same page.
I saw this serverfault question But the issues are:
I could not find the /etc/init.d/networking restart file. I am using Mac and this is for Linux. Also it is an overkill for every-time I test my server. At least 10 times an hour.
Inserting the option SO_REUSEADDR in the code did help Address already in use but I reckon that my server is up but is in a busy state. Using the answer here, I had edited the code to this:
host = <my machine address>
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 8080
s.bind((host, port))
What changes do I make on my server to remove this error in Safari?
Safari can’t open the page "my-ip" because the server unexpectedly dropped the connection. This sometimes occurs when the server is busy. Wait for a few minutes and then try again.
Output of lsof -i:8080, after stopping the script was
python3.7 11881 <user> 3u IPv4 <Device> 0t0 TCP <my machine address>?:http-alt (LISTEN)
I did kill 11881 and then re-run the code but got the same message in Safari.
Output of netstat -na | grep "8080" was
tcp4 0 0 <my machine address>.8080 *.* LISTEN
while the script was running and nothing when I KeyboardInterrupt it.
Firefox shows the page momentarily and then shows the error page
The connection was reset
Chrome shows an empty page only.
Update: It works in python 2.7 but not in 3.5. The difference in the code comes at:
c.send('\n')
in 2.7 and
c.send(bytes('\n'.encode('utf-8')))
in 3.5 where
c is
c, (client_host, client_port) = s.accept()
Rest is all the same.

I had accidentally commented out a line
c.recv(1000)
Where c is mentioned in the question.
I found it when I compared this to an older version of the same file.

Related

python socket gives wrong udp port status of remote server

[user#testserver~]$ sudo nmap -v -Pn -sU -p 152 10.146.25.44
Starting Nmap 5.51 ( http://nmap.org ) at 2022-09-12 16:32 GMT
Initiating UDP Scan at 16:32
Scanning remoteserver.example.com (10.146.25.44) [1 port]
Completed UDP Scan at 16:32, 0.05s elapsed (1 total ports)
Nmap scan report for remoteserver.example.com (10.146.25.44)
Host is up (0.029s latency).
PORT STATE SERVICE
152/udp closed bftp
#!/usr/bin/python #(i am running below code as root)
from socket import *
udp_scan=socket(AF_INET,SOCK_DGRAM)
udp_scan.connect_ex(('10.146.25.44',152))
0 ------------------> this is reported open where as nmap shows udp port 152 is closed
I do not have access to remote server. When checked the remote servers port status, socket modules gives wrong result
Connecting a UDP socket just means that the destination address is set on the socket. There is no actual communication with the remote system going on, contrary to TCP. Thus that the connections succeeds does not allow any conclusion about the remote systems being reachable, ports being open or that the remote system even exists.
Instead one actually needs to send data to the system. The first send will succeed since it returns after putting the data in the local socket buffer, i.e. before actually transmitting the data to the system. Once the packet gets transmitted it might reach the target or might lost somewhere in the middle. Only if the target or some middlebox in between actively reacts to the packet, then a conclusion about the peer can be done. Specifically
if there is an answer somebody is actively replying to the packet
if there is an ICMP unreachable somebody is actively rejecting the packet
if no response happens either the packet got lost, got dropped by a firewall or similar or got actually successfully read by the remote server but without responding

Python socket taking wrong port

Why is my python script behaving this way?
I give it the instruction to connect via port 7777 but instead it is going over 45604.
I am NOT using socket.bind((socket.gethostname(),port))
Instead I work either with socket.bind(("0.0.0.0",port))
or with socket.bind(("127.0.0.1",port))
so I'm working local here. Why does my computer reroute the ports?
There should be no need for that, shouldn't it? Can I somehow disable it locally?
I am answering in the absence of any of your actual code.. So I have to make assumptions here:
1) You have server (right side in picture) listening on port 7777.
2) You are running a client on the same machine (left side of picture) that is connecting to the server.
So, the client (on the left shell) is connecting to the server (right shell window). The server is listening on 7777 and the client is connecting to the server from 45604 (client and server cannot occupy the same port on the same machine!)
Put another way, the client is "sending" to port 7777 from port 45604. Maybe that makes better sense?
A TCP connection is defined by 4 numbers: source IP address, source port, destination IP address, destination port.
The connection goes from 127.0.0.1 port 45604 to 127.0.0.1 port 7777.
The source port (45604) is a value chosen by the system from a wide range of unused ports (it is called an ephemeral port), because your program did not set a specific source port.

Using arbitrary smbserver on port 445

I want to write a totally arbitrary SMB server on my computer.
I'm using Impact (http://code.google.com/p/impacket/source/browse/trunk/impacket/smbserver.py), but the problem (probably) is I can't listen to port 445, as it is already in use by windows.
I've killed the LanmanServer service, but it didn't help.
Running netstat -a I can clearly see port 445 is still in used.
Using CurrPorts I can see that the process that is listening to this port is PID 4 (a.k.a. System process) but obviously I can't (and don't want to) kill it.
On the other hand, just for the sake of it, I've tried to listen to some random port (5002), and check out the SMB server by connecting to \\[my internal ip = 10.0.0.4]:5002\, weirdly enough, this also didn't work out.
I could see some request in Wireshark.. and I know my python process was listening to this port, but it just didn't answer.
On the server I just run this:
SMBSERVER(('10.0.0.4', 5002))

socket.error:[errno 99] cannot assign requested address and namespace in python

My server software says errno99: cannot assign requested address while using an ip address other than 127.0.0.1 for binding.
But if the IP address is 127.0.0.1 it works.
Is it related to namespaces?
I am executing my server and client codes in another python program by calling execfile().
I am actually editing the mininet source code.I edited net.py and inside that I used execfile('server.py') execfile('client1.py') and execfile('client2.py').So as soon as "sudo mn --topo single,3" is called along with the creation of 3 hosts my server and client codes will get executed.I have given my server and client codes below.
#server code
import select
import socket
import sys
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("10.0.0.1",9999))
server.listen(backlog)
input = [server]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
client, address = server.accept()
input.append(client)
else:
l = s.recv(1024)
sys.stdout.write(l)
server.close()
#client code
import socket
import select
import sys
import time
while(1) :
s,addr=server1.accept()
data=int(s.recv(4))
s = socket.socket()
s.connect(("10.0.0.1",9999))
while (1):
f=open ("hello1.txt", "rb")
l = f.read(1024)
s.send(l)
l = f.read(1024)
time.sleep(5)
s.close()
Stripping things down to basics this is what you would want to test with:
import socket
server = socket.socket()
server.bind(("10.0.0.1", 6677))
server.listen(4)
client_socket, client_address = server.accept()
print(client_address, "has connected")
while True:
recvieved_data = client_socket.recv(1024)
print(recvieved_data)
This works assuming a few things:
Your local IP address (on the server) is 10.0.0.1 (This video shows you how)
No other software is listening on port 6677
Also note the basic concept of IP addresses:
Try the following, open the start menu, in the "search" field type cmd and press enter.
Once the black console opens up type ping www.google.com and this should give you and IP address for google. This address is googles local IP and they bind to that and obviously you can not bind to an IP address owned by google.
With that in mind, you own your own set of IP addresses.
First you have the local IP of the server, but then you have the local IP of your house.
In the below picture 192.168.1.50 is the local IP of the server which you can bind to.
You still own 83.55.102.40 but the problem is that it's owned by the Router and not your server. So even if you visit http://whatsmyip.com and that tells you that your IP is 83.55.102.40 that is not the case because it can only see where you're coming from.. and you're accessing your internet from a router.
In order for your friends to access your server (which is bound to 192.168.1.50) you need to forward port 6677 to 192.168.1.50 and this is done in your router.
Assuming you are behind one.
If you're in school there's other dilemmas and routers in the way most likely.
This error will also appear if you try to connect to an exposed port from within a Docker container, when nothing is actively serving the port.
On a host where nothing is listening/bound to that port you'd get a No connection could be made because the target machine actively refused it error instead when making a request to a local URL that is not served, eg: localhost:5000. However, if you start a container that binds to the port, but there is no server running inside of it actually serving the port, any requests to that port on localhost will result in:
[Errno 99] Cannot assign requested address (if called from within the container), or
[Errno 0] Error (if called from outside of the container).
You can reproduce this error and the behaviour described above as follows:
Start a dummy container (note: this will pull the python image if not found locally):
docker run --name serv1 -p 5000:5000 -dit python
Then for [Errno 0] Error enter a Python console on host, while for [Errno 99] Cannot assign requested address access a Python console on the container by calling:
docker exec -it -u 0 serv1 python
And then in either case call:
import urllib.request
urllib.request.urlopen('https://localhost:5000')
I concluded with treating either of these errors as equivalent to No connection could be made because the target machine actively refused it rather than trying to fix their cause - although please advise if that's a bad idea.
I've spent over a day figuring this one out, given that all resources and answers I could find on the [Errno 99] Cannot assign requested address point in the direction of binding to an occupied port, connecting to an invalid IP, sysctl conflicts, docker network issues, TIME_WAIT being incorrect, and many more things. Therefore I wanted to leave this answer here, despite not being a direct answer to the question at hand, given that it can be a common cause for the error described in this question.
Try like this:
server.bind(("0.0.0.0", 6677))
When you bind localhost or 127.0.0.1, it means you can only connect to your service from local.
You cannot bind 10.0.0.1 because it not belong to you, you can only bind ip owned by your computer
You can bind 0.0.0.0 because it means all ip on your computer, so any ip can connect to your service if they can connect to any of your ip
This is not directly answering the question, but is a debugging direction in case above solutions failed.
When you are not on a native environment, let's say you are on a VM or WSL, the inside network might not be transparent to external computer due to NATing. So make sure you can ping the IP from wherever you are trying to bind. If not, then consider switching to the correct environment or consider network bridging.
If you are looking for a WSL2 specific solution, you may try this link:
Bridging WSL2 network adapter with Windows
In Virtual Box you may change Network Adapter -> Attached To: Bridged Adapter.
The other consideration is if you are trying to bind to a port <1023 you need admin privilege.
This was what I need on a remote VM:
jupyter notebook --ip=0.0.0.0 --port=8888
Copied from here

python Socket server with real ip address

I am playing with my python server, but I'm through with using localhost and I want to go over the internet. My code thus-far is:
import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
cur_thread = threading.current_thread()
response = "{}: {}".format(cur_thread.name, data)
self.request.sendall(b'worked')
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
try:
sock.sendall(message)
response = sock.recv(1024)
print("Received: {}".format(response))
finally:
sock.close()
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "0.0.0.0", 9001
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
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)
ip = '12.34.56.789' #Not my real ip address This is just to hide my ip
print(ip, PORT)
client(ip, PORT, b'Hello World 1')
#client(ip, port, b'Hello World 2')
#client(ip, port, b'Hello World 3')
server.shutdown()
When I run this i get the error:
Server loop running in thread: Thread-1
12.34.56.789 9001
Traceback (most recent call last):
File "C:/Python32/serverTesty.py", line 43, in <module>
client(ip, PORT, b'Hello World 1')
File "C:/Python32/serverTesty.py", line 18, in client
sock.connect((ip, port))
socket.error: [Errno 10061] No connection could be made because the target machine actively refused it
I know the port works because when I use canyouseeme.org on port 9001 when my program is running it says its active and working. So I think I just have my connection wrong somewhere.
ip = '12.34.56.789' #Not my real ip address, its the one i got from whatismyip.org
The first problem is that '12.34.56.789' isn't a valid IP address at all. Each component has to fit in 8 bits (0-255); 789 is impossible. But I assume that isn't the actual code you're running, because the output shows 12.45.29.122.
The second problem is that you're using an address that isn't your real address.
Your machine presumably has an internal IP address, that can only be accessed from your LAN. Then, your router has an external IP address. The router uses a technique called Network Address Translation to let each machine on your LAN pretend that external address belongs to them, when they're acting as clients (which is why whatismyip.org shows you that address). But that doesn't work when they're acting as servers.
If you think about it, there's really no way it could work. If you make an outbound connection, and someone replies, the router knows that the reply should go to your machine. But if someone just comes along and talks to the router out of the blue, how could it know which machine to send the connection to?
If you're trying to connect from inside the same LAN, there's a very easy solution: use the server's real internal address, not the router's external address.
If you need to connect from outside, you can't, without some extra work. There are four ways around this:
Give your machine a real publicly-addressable IP address (e.g., by putting it on the router's DMZ). This is generally not even an option for home users, and it's a bad option for people who don't know what they're doing (unless you want your machine to be part of someone's botnet by lunchtime).
Set up static port forwarding in your router's configuration. This is different for each router, but the idea is that you tell it "if someone comes looking for port 9001, always send them to machine 192.168.1.64".
Use UPnP to set up port forwarding dynamically.
Set up a NAT hole punching.
Options 3 and 4 are more complex, and I think option 2 is the one you want, so I won't explain them.
On top of all that:
HOST, PORT = "192.168.1.64", 9001
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
You've told the server explicitly "listen on 192.168.1.64". Even if you put your server machine on the DMZ, so it had addresses 192.168.1.64 and 12.45.29.122, your program is only listening for connections on the first one, so nobody would be able to reach it using the second. If you want to listen on all addresses, use 0.0.0.0.
In the edited version, you're now listening on 0.0.0.0, and connecting to the router's public IP, and you claim to have set up port forwarding on the router, and you're still getting the exact same error.
If that's all correct, there are three obvious things that could be going wrong:
You're not actually port forwarding; something is wrong with the setup.
You're not actually listening on 0.0.0.0:9001.
You've got a firewall blocking the connection.
There are a few tests you can do to narrow things down.
Open two terminals. In one, type nc -kl 9001. In the other, type nc 12.34.56.78 9001. They should connect up, so anything you type into one window appears in the other (maybe only after you hit Return). If that works, the port forwarding is working, and there's no firewall problem, so it's a problem in your code.
If that didn't work, please post exactly what you saw in each window. Then Ctrl-C the second nc, and type nc 192.168.1.64 9001. If that now works, either the port forwarding isn't set up right, unless you have a clever firewall that allows same-host (or same-interface) connections but not remote connections.
If neither one worked, it's probably a firewall problem. (Unless you're wrong about your IP addresses or something.) You can probably find logs somewhere, but without knowing what platform you're on and what firewall you're using it's hard to offer much help. (Also, that's probably a problem for a different site than SO.)
If you're on Windows, or some linux distros, you need to get a copy of nc (netcat) from somewhere; on most linux distros, and Mac, it should be built in. Also, GNU, BSD, and Hobbit nc are slightly different, so if nc -kl 6000 gives you an error, you might have to read the man page or --help. (If I remember right, Hobbit nc requires -l -p6000, BSD requires -l 6000, GNU allows either.)
Or you may want ncat, a re-implementation of netcat that I know can handle the syntax I used above, and has a single-file static executable for Windows.
If you can't get started with nc, at least try changing your code to connect to 192.168.1.64 instead of 12.34.56.78. If that fixes the problem, at least you'll know it's either port forwarding or a firewall that allows same-host/interface connections but not remote.

Categories

Resources