Python can't connect to open socket on the same network - python

I have started a simple python socket, and I can freely connect to it from my local computer, but from iPad and another computer, I can't access it! What I am doing wrong? Here is my code:
from socket import socket
server = socket()
server.bind(("", 80))
server.listen(2)
message = """\
</pre><br><br><h1>Hi!</h1></body></html>
"""
while 1:
c, a = server.accept()
print "New connection from %s:%s"%tuple(a)
c.sendall("<html><head><title>Hi!</title></head><body><pre>"+c.recv(4096*20)+message)
c.close()
EDIT
Btw, I am using Linux Fedora 18. On Windows, I didn't have problems with sockets.

In the docs on socket:
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.
The default behavior is likely to host on localhost. Try setting host to "0.0.0.0" to allow connectivity outside localhost.

Related

Create TCP Server accessible on remote networks

A project I am working on has an Android app as a front-end and a Python program that would be used as the back-end.
I want to send data from the Android app (primarily images) to the Python program, do some processing and send the result back to the Android app.
I have found numerous tutorials that suggest using the socket module in python to create the server side, but all tutorials show the server on local network only (For testing purposes I created the client side also in Python, but it would be converted to Java later on)
The server code:
from requests import get
import socket
public_ip = get('https://api.ipify.org').text
print('My public IP address is: {}'.format(public_ip))
# getting the hostname by socket.gethostname() method
hostname = socket.gethostname()
# getting the IP address using socket.gethostbyname() method
local_ip = socket.gethostbyname(hostname)
# printing the hostname and ip_address
print(f"Hostname: {hostname}")
print(f"IP Address: {local_ip}")
#
HOST = local_ip
PORT = 80 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024).decode('utf-8')
if not data:
break
conn.sendall(data.encode('utf-8'))
The client code:
import socket
HOST = '…' # I modify it to the server's public IP address, as printed from the server code
PORT = 80 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
with socket.create_connection((HOST, PORT)) as s:
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
Using the code above, if I try using any port other than 80 I get ConnectionRefusedError: [Errno 111] Connection refused. And for port 80, I get TimeoutError: [Errno 110] Connection timed out.
In both cases, I try to connect from a device on another network.
I tried to use the ping command in Windows CMD to check the connection to the server, and I get 'connection refused message'.
I understand that the Firewall is what probably blocks the connection, but I don't know how to bypass it. I added a new rule in the Inbound Rules section (as suggested on other websites) but for no avail… The results were the same.
How can I make the connection between remote devices on different networks?
Thanks in advance ☺
In order to connect to your server using a TCP socket connection, you need to make sure your server can listen on a port on a publically available IP address.
If the External IP address is assigned to your computer directly,
and if you run the server code on that computer, then the TCP port opened by the server code should be available on the internet.
However, IP addresses are often assigned to a modem/router in home networks,
instead of assigning them to any connected device directly.
To find out if your External IP address is assigned to the computer directly you can use tools that your OS support (eg. ipconfig on windows). If you can see the IP address returned by api.ipify.org, then it means your computer is connected directly. You can change your code to connect using publically exposed IP:
HOST = public_ip
If this is successful means your computer is assigned an external address directly. Which is highly unlikely.
There are several workarounds for this problem though:
1) Configure your router to forward port
Configure your router to forward all connections to it's external TCP port, to an internal host in your network which is assigned to your computer. Please find instructions how it is done for your router.
2) Setup a remote proxy
If you don't have permission to change your router settings you can set up a remote proxy listening on the TCP port. While there is a number of ways of doing this, very popular is to set up a remote SSH tunnel, for that you need to have a server with SSH access and an external IP. Run this command:
ssh -R 80:localhost:8080 root#your-ssh-server-host
You can also use a third-party service that exposes your private host on the internet like:
Ngrok (Commercial, with free plans)
Localtunnel (Open Source, can be self-hosted)

Socket Programming - How to connect a remote address

I am practicing socket programming using python. I am fimiliar with how to make a simple tcp server and client in local address but I want to know how to make it possible so that I can connect to my own computer from a client app that I built. What modifications do I have to make in this server script? or client?
server:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#The host is set to be the local machine.
address = ("127.0.0.1",1234)
s.bind(address)
s.listen(1)
c , addr = s.accept()
while True:
#do some stuff
c.close()
client:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
address = ("127.0.0.1",1234)
s.connect(address)
while True:
#Do client stuff
s.close()
I'm not allowed to make comments yet. But if you have a client app on another device, you can make the HOST your machines IP that stores the server. IF you're using windows ENTER: ipconfig In your command line argument. I think that or Linux its if config. You should be able to set your address to your machines ip address in order to get the client to connect to your local machine. As you noted, localhost will not work.

Python 2.7 Socket connection on 2 different networks?

Title says all. I have a client and a server setup, but they only work with localhost. How can I connect to the socket from a different network?
Client
# Echo client program
import socket
print "Client"
HOST = "localhost" # Symbolic name meaning all available interfaces
PORT = 5001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
while True:
data2 = raw_input()
s.sendall(data2)
Server
# Echo server program
import socket
print "Server"
HOST = "" # Symbolic name meaning all available interfaces
PORT = 5001 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
print data
if data == "Ping":
print "Pong!"
conn.close()
Check your public ip address using online tools like http://whatismyipaddress.com/
Check your local ip address using ipconfig -a in windows ifconfig in linux.
Now if you are behind a dsl router (generally, you are) these addresses are completely different. So you have to tell your router to send whenever a connection attemp received to a TCP port XXXX , forward it to "My Machine" (called Port Forwarding ). Although port forwarding settings are similar in most routers, there is no standard (Generally under NAT / Port Forwarding menu items on your router web configuration interface ). You may have to search instructions for your specific model.It's a good idea to set your computer to use a static ip address before port forwarding.Otherwise, the settings will be invalid if your computer is assigned another IP adress via DHCP.
If port forwarding is successful, now you only have to set your client application to connect to your public ip address. In your specific situation it's HOST = "X.X.X.X" in your client source code. Check if port forwarding works with a socket tester application you downloaded from somewhere. ( Don't test it with your experimental code, use an application you are sure that it's working). All did not work, check out the note below. It's the last resort ,though.
Note : Some ISP's put their clients behind an extra firewall for security. A simple method to detect if this is the situation is , your Wan ip address you see in your router web interface will be different from what you see in online tools like whatsmyip. In this situation no matter what you do , you will not be able to connect. You have to call your ISP and tell them to disable firewall for your connection . You may have some difficulties to explain them what you are talking about :).

Python Sockets: Connection Timeout

I'm trying to write two short python scripts that will connect two or more machines to each other, one as the server and the others as clients. It worked perfectly when testing the client and the server script on the same computer, but when I tried it from another computer the client kept timing out; it couldn't connect to the server. Here's my server code:
import socket
server = socket.socket()
host = "computername"
port = 12345
server.bind((host, port))
server.listen(5)
client, addr = server.accept()
Client code:
import socket
server = socket.socket()
host = "computername"
port = 12345
server.connect((host, port))
Any clue as to why the machines can't connect?
I think, you are changing host variable properly when running both client and server scripts in different machines. Try by changing that properly/or using IP address of server machine.
The communication could be prohibited by a firewall.
To rule out DNS related problem, try IPs instead of hostnames:
# server: listen on all interfaces
server.bind(('', port))
and:
# client: specify server's IP address
server.connect(("192.168.XX.YY", port))
with a real IP address, of course.

Python socket on Windows 7 is not accessible from another machine

I'm trying to create a Python program that will listen on a socket. I'm using Windows 7 with Python 2.7. Whatever I do, the socket seems to be accessible from the local machine but not from elsewhere on the network.
I've got the following code:
from werkzeug.wrappers import Request, Response
#Request.application
def application(request):
return Response('Hello World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
# Using empty string or the machine's real IP address here
# gives the same problem
run_simple('0.0.0.0', 4000, application)
If I connect from the local machine I see the response fine. If I execute
$ curl 'http://192.168.1.1:4000/'
from another (linux) box on the network, the curl hangs for a long time before timing out. Wireshark shows that I receive a SYN packet to port 4000 but don't see it ACKed.
I've tried making sure packets to this port are allowed through the firewall (the fact that I see the SYNs in Wireshark suggests this is not the problem). I've tried setting Python to run as administrator (and I've checked that ctypes.windll.shell32.IsUserAnAdmin() returns true). This isn't just Werkzeug, I've tried with SocketServer from the Python standard library as well.
Running Windows Apache on the same port works fine from across the network, which suggests there's no problem with the network or firewall or with my curl request.
netstat -an shows:
TCP 0.0.0.0:4000 0.0.0.0:0 LISTENING
Edit: I've tried with the following minimal code. On the server side (Windows 7):
import socket
s = socket.socket()
s.bind(('', 8080))
s.listen(1)
remotesock, addr = s.accept()
And on the linux client:
import socket
s = socket.socket()
s.connect('192.168.1.1', 8080)
This hangs until timeout, as with the curl.
I believe the problem is due to your address binding. Python does not allow sockets bound to localhost (or 0.0.0.0) to be visible from the outside world. Change the binding to your actual IP Address.
EDIT: Showing example code
Change your code to this
import socket
s = socket.socket()
s.bind(('192.168.1.1', 8080)) # assumes your machine's IP address is 192.168.1.1
s.listen(1)
remotesock, addr = s.accept()

Categories