I am trying to implement a simple TCP instant messaging program in Python using the socket module. When I use the value returned by socket.gethostname() in connect(), the client works perfectly fine when connecting to the IM server running on localhost. However, the client returns errno 111 (Connection refused) when I use the value returned by socket.gethostbyname("localhost"). Is there any way to fix this issue?
If you get a 111 when trying to connect, that generally means nothing is listening at that host and port.
It's usually easier to check this with a one-liner using netcat (which you probably have built-in on any platform but Windows, and can get easily if you don't), or telnet if you must:
abarnert$ nc -v localhost 111
nc: connect to localhost port 111 (tcp) failed: Connection refused
nc: connect to localhost port 111 (tcp) failed: Connection refused
nc: connect to localhost port 111 (tcp) failed: Connection refused
Since netcat couldn't connect, the problem isn't your Python client, it really is that there's nothing to connect to.
This means your server isn't listening on localhost:111.
Without knowing anything about your server beyond a brief mention, it's impossible to diagnose, but my first guess would be that you're doing a bind((gethostname(), 111)), which means it ends up listening only on, say, 10.0.0.3:111.
If you want to listen on all hosts and interfaces, there are fancy ways to specify that, but the easiest way is:
serversocket.bind(('', 111))
Related
I'll try be concise, but please let me know if I can provide any more helpful pieces of information.
I have client and server Python programs, and they work fine when ran on the same machine, and when the client connects to my machine's local IP (not 127.0.0.1, but the IP assigned to my machine). I have not been able to get this to work with my public IP.
I get a [Errno 61] Connection refused error when I try to get the client to connect to my router's public IP address. My server binds to all interfaces using bind(("0.0.0.0", 50000)), and I already set up port forwarding for my router. I verified that the program is listening on that port by running netstat -an | grep LISTEN and finding the following line:
tcp4 0 0 *.50000 *.* LISTEN
I can also seemingly reach the port through an online port checking tool, which shows that the port is open when I am running my program, and closed when I close that program. My program also registers the connection from this tool.
The fact that my program accepts the connection from the port checking tool gives me the impression that my client code is missing something, but I can't find any answers. It might be worth noting that I am still running my server and client code on the same machine, but I'm not sure why that would derail things. Here's the code I use to connect on the client side:
tcp_client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
tcp_client.connect(('my_public_ip', 50000))
Are there any diagnostic steps that I can follow to narrow down my issue?
Before you spend any more time on this, try connecting to your public ip from a computer outside your home network. Spend a couple of dollars on an AWS instance for an hour if you have to, or try connecting from a friend's machine, whatever. It will probably work just fine.
I suspect the problem is simply that you cannot, from inside your home network, connect to your router's public ip address. I tried the same thing with my local network and ran into the same behavior.
If you really need to your public ip during development, you can just assign that as an alias to one of your local interfaces (ip addr add 1.2.3.4/32 dev eth0)...but it's probably easier just to use your an address on your local network, or just arrange for regular access to a remote system for testing.
So for personal reasons, I want to connect to a socket I create via telnetlib, I can connect to it from netcat but when I try from python it refuses the connection.
tn.write(b"/usr/bin/nc -l -p 3333 -e /bin/sh\n")
print("netcat listening on 3333 on target, trying to connect")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((tn.host, 3333))
s.send('ls')
print(s.recv(1024))
s.close()
If I can connect to it via netcat (by putting for example and infinite loop after tn.write())
You have a classic race condition:
The packet containing the command to start an nc is sent at only nanoseconds before the connection request (TCP SYN packet) of s.connect. It can even happen that the SYN gets to the remote host before the command to start nc.
You need to add proper synchronization. From the code you have shown, there is really no need to use two channels in the first place, so why not send the ls via the existing telnet channel to the remote host?
If you absolutely must use a second channel, try one of these options:
Add import time and time.sleep(5) just before calling s.connect. That way, the connection attempt will be deferred by 5 seconds. However, in general, there's no guarantee that 5 seconds is enough.
Send an additional command to wait for the port to be taken, as a sign that nc is ready.
Retry multiple times (and wait in between).
Also note that your code has three different security vulnerabilities:
You are using telnetlib, which neither ensures confidentiality nor integrity of commands, output and passwords. Use ssh instead.
You are connecting to port 3333 in plain, which neither ensures confidentiality nor integrity of commands and output. Use ssh instead.
In between nc starting and your program connecting to it, anyone can connect to port 3333 and run arbitrary commands. Use ssh instead.
I am very new to socket programming. I am trying to connect to a power supply over ethernet. My Mac (OS X) is connected to an ethernet switch and the power supply is also connected to the switch. I have some code written in python to send/receive commands/messages to/from the power supply.
The switch interface allows me to assign a static IP to the supply. It is this same IP that I use as the target IP in the following code:
def __init__( self, IP_TARGET ):
IP = IP_TARGET
PORT = 8080
self.supply = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
self.supply.connect( (IP, PORT) )
This code runs without any issues. My next goal is communicate with the device using the following code:
def getDeviceInfo( self ):
self.supply.send('some command ')
self.supply.recv(10)
Using some print statements I have narrowed the issue down to the recv() command. The send() throws no errors. I get the following error
...in getDeviceInfo
self.supply.recv(10) socket.error: [Errno 61] Connection refused
I am able to ping the device using the IP that I assigned it using the ethernet switch. I have firewall off. I have searched the www for clues as to how I might resolve this error, but to no avail. Any thoughts?
It looks like there is nothing running on the host and port you specified (you can check it with nmap, for example).
In the case it does, is it expecting to receive anything and responding to it?
EDIT: your code is not working because in the remote host and the port you specified (8080), there must be some some code running, listening for messages and responding to them. If there is nothing running on that port, it obviously returns you the "Connection refused" error.
In other words, you created the client, but not the server :P
The port I chose was random (I thought anything above 4096 would be
okay).
See the Digi Connect® Family Command Reference on how to Access the Command Line.
The Command-Line Interface for the Digi device uses the telnet port, which is TCP port 23.
(The port number restrictions you were probably thinking of apply only if you do the server.)
I am trying to do some simple sockets programming in Python. I have a UDP server in Python that accepts an input and sends a response. I'm having trouble with the client code.
sock = socket.socket(
socket.AF_INET, socket.SOCK_DGRAM
)
sock.bind(('0.0.0.0', 0))
sock.settimeout(2)
sock.sendto(json.dumps({
'operation': operation,
'operands': [operand1, operand2]
}), (host, port))
print sock.recvfrom(4096)
This code works perfectly when the server is running. However, when I try it without the server running, the code throws an exception immediately instead of blocking on recvfrom().
socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host
My desired functionality would be to timeout after some time.
Can anyone explain what I am doing wrong? I use recvfrom in the server code and it blocks, so I'm a little puzzled at what the difference is.
Much of the former answer doesn't apply, since you have a SOCK_DGRAM type, i. e. UDP socket. UDP is a connectionless service, even though the error message talks about connection. The exception occurs due to a notification from the destination host in response to the sendto datagram, telling that the port is unreachable; this notification is processed (perhaps even arrives) not before you call recvfrom. There is no automatic retry; you have to try the recvfrom (maybe as well the sendto) again and implement the desired timeout yourself.
There are plenty possible reasons for that.
Socket error [10054] means connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
Check this link for details.
You need to look into it to figure out what actually happened. I don't have your environment so I cannot locate what the real problem is.
Hope this helps.
I would try connect to a counterstrike server hosted on my ip through python socketing ...
import socket
s = socket.socket()
s.connect(("localhost", 27015))
But I would get an error
error: [Errno 10061] No connection could be made because the target machine actively refused it
And I'm sure the server is up, so I'm not sure why it wouldn't connect, I could connect to it in game.
To debug such things you can use Wireshark to observe your Python script while it is trying to connect and compare it to a real client. You may have to listen on the "localhost" interface instead of your physical network interface to see the connection. Your server needs to do the same, so ask your OS to give you a list of bound sockets, including the IPs they are bound to (on Linux netstat -nlp) to check. Maybe the server needs to be configured to allow non-public IPs. Finally, make sure you got the protocol right, TCP (SOCK_STREAM) vs UDP (SOCK_DGRAM).