I'm working with a bit of Python that looks like this:
HOST = '127.0.0.1'
PORT = 43434
single = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
single.bind((HOST, PORT))
except socket.error as e:
# Print an error, exit.
While it's been functioning well in the past, we now get the error [Errno 98] Address already in use. The SIGINT handler closes the socket connection, so I'm not sure how it got in that state, but for now I'm just trying to fix it.
Both lsof and netstat say there's nothing using that port:
[$]> sudo netstat -an | grep 43434
[$]> sudo lsof -i :43434
TIME_WAIT is set to 60 seconds, according to /proc/sys/net/ipv4/tcp_fin_timeout, but the error occurs even hours after last run successfully.
I've tried (temporarily) setting REUSEADDR (via single.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)), but that appears to have no effect.
What in tarnation is going on? Will I ever be able to use this port again without having to reboot the machine?
Try this:
tcpkill -i eth0 port 43434
I wanted to add a comment but It will not let me do so. so I have to answer this way. In my experience I have had to do the following to get sockets to work with any success. I've had to explicitly set the timeout myself.
In your code before you open the socket, you should set this if you are using python version 2.3 or later. I usually start with a timeout of 30 seconds and then tune it to what works for a particular website. When I don't use this parameter i get flakey issues.
socket.setdefaulttimeout(timeout)
Other issues I've done after the open are catch some of the following exceptions:
except socket.gaierror, err:
# you might want to handle this
except socket.sslerror, err2:
# you might want to handle this if doing SSL
You could try to set SO_REUSEPORT socket options. HOwever, it only works if the conflicting socket also had the SO_REUSEPORT options set before it was bound, so you should try after a clean reboot.
However, you said your python code looks like the code you posted. Have you actually tried a very simplified version of your program to test only the binding ?
You can also try to strace your program.
Related
I’m trying to create a server on my raspberry pi using python and then i want to test the server by accessing it from another device using the IP address of the raspberry pi, but the problem is that everytime i type the IP address of my raspberry pi into my webpage, it doesn’t open and i don’t know if there’s a problem in my code or not, i will write below so that anyone could check
import socket
import sys
my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
try:
my_socket.bind((host, 1234))
except socket.error:
print(‘failed’)
sys.exit()
my_socket.listen(5)
While True:
conn, addr = my_socket.accept()
data = conn.recv(1000)
if data:
print(‘got a request’)
my_socket.send(‘Thank you’)
my_socket.close()
conn.close()
after that i tried typing the raspberry pi’s IP address on my laptop’s webpage but it was no use, first i typed ifconfig in the terminal of the raspberry pi to get the IP address and i tried it but it didn’t work, then i added another line in the code which is gethostbyname to the variable host and printed it and it showed different IP address than the one in ifconfig which was confusing to me, but i even tried this another IP address on my webpage and it didn’t work too
Did you check with netstat to see if the code is actually listening? Should list the <IP>:<Port> as LISTENING, i always check that when i do server code.
Sometimes when you try out code and don't terminate it properly, there can be a orphan process still listening to the Interface:Port hogging the port. Been there, done that, got the T-shirt.
Also, try using 0.0.0.0 instead, it tells the socket listener to listen on all interfaces, including loopback.
Got any firewall denying the connection ? Check that.
Also, check try using curl as a debug tool and see if 1) Curl can connect and 2) you get send some HTTP data to the server:
Curl 127.0.0.1:1234/HelloWorld
I start a server using sockets and want to allow clients to connect to it.
self.sock.bind(('0.0.0.0',0)) # 0.0.0.0 will allow all connections and port 0 -> os chooses a open port.
stroke_port=self.sock.getsockname()[1]
self.sock.listen(75)
self.open_port_popup(stroke_port)
Now, for other clients to connect I have port forward it manually and it works fine.
I want to do this in automated fashion. -> I try upnp.
import miniupnpc
def open_port(port_no):
'''this function opens a port using upnp'''
upnp = miniupnpc.UPnP()
upnp.discoverdelay = 10
upnp.discover()
upnp.selectigd()
# addportmapping(external-port, protocol, internal-host, internal-port, description, remote-host)
result=upnp.addportmapping(port_no, 'TCP', upnp.lanaddr, port_no, 'testing', '')
return result
It opens a port shown in the image below. But the port-forwarding list shown in the first image is empty. It doesn't work and clients can't connect. How can I fix this? What am I missing?
I think you made a mistake using upnp.lanaddr as internal-host address. upnp.lanaddr is the address of the upnp device which is your router, you want to use the local address of your server.
If needed take a look at Finding local IP addresses using Python's stdlib if you want to get your server local IP dynamically.
I think that we are missing lot of related info to know what's the main problem here. I see so many people guessing.
By the way, just editing that line
result=upnp.addportmapping(port_no, 'TCP', upnp.lanaddr, port_no, 'testing', '') to
result=upnp.addportmapping('7777', 'TCP', '192.168.1.8', '7777', 'testing', '') would tell you if it works at all.
Doing port testing from localhost it's dummy, you're not under the router at all.
Also, remember to use Try/Except blocks to tell you what's wrong on your code.
try:
print "1" + 1
except Exception as e:
print str(e)
Another way, not fashioned is to use html/web automation, even cURL to make those requests instead using uPnp, this way you don't really need to handle it.
Most of the time ISP don't allow port forwarding, and you spend hours on this trying to forward port.
I went for ngrok - it's a lightweight free of cost (for basic usage) program that tunnels the port and give its own tunneled domain which can be accessed everywhere.
this is interesting question.
from what I could summon I think
GUI shows that UPNP port forwarding rules are added.
so Most likely there is issue in UPNPC configuration.
I doubt you are doing this on Router or similar platform with X-WRT or OpenWRT
the issue I think is you can't use upnp for this or it doesn't work for some strange reason.
I suggest you try this library pytables.
I know you wanted to know why and I am working on figuring out the reason.
this is just for you to get going on this project
and for quick solution
Try this
import subprocess
p = subprocess.Popen(["iptables", "-A", "INPUT", "-p", "tcp", "-m", "tcp", "--dport", "22" , "-j", "ACCEPT"], stdout=subprocess.PIPE)
output , err = p.communicate()
print output
I am running a script that telnets to a terminal server. Occasionally the script is launched while one instance is already running, which causes the already running script to fail with
EOFError: telnet connection closed
Is there a quick and easy and pythonic way to check if the required socket is already in use on the client computer before I try to open a connection with telnetlib?
SOLUTION:
I wanted to avoid making a subprocess call but since I do not control software on the client computers, and other programs may be using the same socket, the file lock suggestion below (a good idea) wouldn't work for me. I ended up using SSutrave's suggestion. Here is my working code that uses netstat in Windows 7:
# make sure the socket is not already in use
try:
netstat = subprocess.Popen(['netstat','-nao'],stdout=subprocess.PIPE)
except:
raise ValueError("couldn't launch netstat to check sockets. exiting")
ports = netstat.communicate()[0]
if (ip + ':' + port) in ports:
print 'socket ' + ip + ':' + port + ' in use on this computer already. exiting'
return
You can check for open ports by running the following linux command netstat | grep 'port number' | wc -l by importing subprocess library in python.
There is not a standard way to know if a server has other opened connections before you attempt to connect to it. You must ask it either connecting to another service in the server that checks it, or by asking the other clients, if you know all of them.
That said, telnet servers should be able to handle more than one connection at a time, so it should not matter if there are more clients connected.
I'm about to do a simple testimplementation to use PagSeguro (brazilian "PayPal"), and for this I downloaded their Python server to do tests on my localhost. I work on a Mac, have a XAMPP server (Apache and MySQL parts on during my process).
My problem should be very simple for someone who knows Python and sockets etc, and I did found a lot of clues in my information searches. However - with my own poor knowledge in this area, I wasn't able to put two and two together to fix it.
Short question: How do I free a socket (from Terminal) whos program quit before it had closed the socket. Alt - how do I make a Python function for me to call when I want to close the socket and stop/restart the server.
Scenario:
I start the server (In terminal with #: sudo python ./PagSeguroServer.py) and it works fine, I did some of the tests I wanted to. Then, I needed to change some settings for the server, and to make it work i need to restart the server. I resolved by closing the terminal window, but then when I reopen and type the same command to start the server again I get the "socket.error: [Errno 48] Address already in use". Ok I can see why but not how to fix, so I Google that, and find the tip to add
socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
in the code. Looked at the Python class and tried to put it there to my best knowledge (as below). However, didn't solve my problem. Since my "search and puzzle" doesnt seem to be able to help me - I'm now giving it up and posting this customized question instead!
This is part of the server code:
class SecureHTTPServer(HTTPServer):
'''Servidor HTTPS com OpenSSL.'''
def __init__(self, server_address, HandlerClass,fpem):
BaseServer.__init__(self, server_address, HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file (fpem)
ctx.use_certificate_file(fpem)
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
self.socket_type))
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_bind()
self.server_activate()
....
def run(HandlerClass = HTTPSHandler, ServerClass = SecureHTTPServer):
'''Roda o servidor'''
server_address = ('', 443) # (address, port)
httpd = ServerClass(server_address, HandlerClass, fpem)
httpd.serve_forever()
if __name__ == '__main__':
run()
Note: One time I actually did managed to reopen it - it was before I added the setsockopt call, and I got the feeling that the socket had closed after a timeout - read about that somewhere. This however doesn't seem to happen again - have waited and tried several times.
Edit: In the end this is how I resolved: Needed to kill the python process that was holding the socket (see comment on jd's answer), then added the KeyboardInterrupt catch to be able to close the socket correctly. Thanks all!
If you're using Ctrl+C to close the process, you could try catching the KeyboardInterrupt exception (or even better, handle the SIGINT signal) in your code and cleanly close the socket before exiting.
Of course, this won't prevent you from killing your application in some other manner and having a stale socket, but you can try to handle those cases as well.
You could create a function that closes the socket properly and register it to be run at program termination using atexit.register(). See http://docs.python.org/library/atexit.html
Use the following command in a terminal window to kill the TCP port 28355:
npx kill-port 28355
In my python socket server script I used the following lines:
import os
os.system("npx kill-port 28355")
This command solves the "Address already in use" error.
It was the only solution that solved the error out of all the other solutions I found, like enabling the SO_REUSEADDR option.
AFAIR SO_REUSEADDR works a bit different.
But what you should start with - when you kill your working server type
netstat -tapdn |grep PORT
and replace PORT with PORT of yoiur application
Than you will get info about state of the socket....
On OSX you can kill the port(e.g. 8000) with:
kill `lsof -i :8000 | grep Python | cut -c8-11`
hth
In Hyperterminal I am able to connect to a serial port called "X64-CL_iPro_1_Serial_0" where I am able to send/receive ASCII text to a camera. However when I try to connect to the same port with pySerial, it throws an exception:
SerialException: could not open port X64-CL_iPro_1_Serial_0: [Error 2] The system cannot find the file specified.
I don't understand why Hyperterminal can detect the port and communicate with it, but Python can't. I downloaded this script from the pySerial website that displays a list of serial ports, and the only ports it came up with was COM1 and COM2, neither of which I can connect to.
My code is very simple, and looks like this:
import serial
port = "X64-CL_iPro_1_Serial_0"
ser = serial.Serial(port)
Am I doing anything wrong? Is there a way to work around this? Thanks ahead of time.
Edit:
It should also be noted that this port does not show up in the device manager, and neither does COM1 or COM2.
The problem lies in the enumeration code you linked. It is wrong in two regards:
It uses a fixed GUID_CLASS_COMPORT to enumerate. It should instead ask the GUID through SetupDiClassGuidsFromName, passing "Ports" as description of the class for which it is asking for names.
The code insists of asking for the friendly name of the port. But if the only goal is to open the device (instead of displaying to an user), it should directly access the DevicePath element, which is a weird-looking-but-perfectly-valid port name to pass to pySerial. The friendly name might even be totally missing.
aside
I'm not clear the question is about non-serial-port use through pyserial, or serial port that is not a COMX port in enumeration.
This may be a bit OT or too hard code for your use, but here goes first, using some other file in a pyserial object:
foo = serial.Serial()
peer = serial.Serial()
foo.fd, peer.fd = posix.openpty()
try: foo._isOpen = peer._isOpen = True # depending on pyserial version
except: pass
foo._reconfigurePort()
peer.setTimeout(timeout=0.1)
peer._reconfigurePort()
Regarding second, remember that ports beyond COM9 use weird windows notation \\.\COM10, perhaps that's what Hyperterminal does for you. pyserial doesn't do it, so perhaps you need to open the port something like this:
s = serial.Serial("\\\\.\\X64-CL_iPro_1_Serial_0") # also remember to escape backslash