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()
Related
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)
I am using server(server_name.corp.com) inside a corporate company. On the server i am running a flask server to listen on 0.0.0.0:5000.
servers are not exposed to outside world but accessible via vpns.
Now when i run host server_name.corp.com in the box i get some ip1(10.*.*.*)
When i run ifconfig in the box it gives me ip2(10.*.*.*).
Also if i run ping server_name.corp.com in same box i get ip2.
Also i can ssh into server with ip1 not ip2
I am able to access the flask server at ip1:5000 but not on ip2:5000.
I am not into networking so fully confused on why there are 2 different ips and why i can access ip1:5000 from browser not ip2:5000.
Also what is equivalent of host command in python ( how to get ip1 from python. I am using socktet.gethostbyname(server_name.corp.com) which gives me ip2)
As far as I can tell, you have some kind of routing configured that allows external connections to the server by hostname (or ip1), but it does not allow connection by ip2. And there is nothing unusual in this. Probably, the system administrator can advise why it is done just like this. Assuming that there are no assynchronous network routes, the following function can help to determine public ip of server:
import socket
def get_ip():
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(("8.8.8.8", 80))
local_address = sock.getsockname()
sock.close()
local_address = local_address[0]
except OSError:
local_address = socket.gethostbyname(socket.gethostname())
return local_address
Not quite clear about the network status by your statements, I can only tell that if you want to get ip1 by python, you could use standard lib subprocess, which usually be used to execute os command. (See subprocess.Popen)
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.
so I'm trying to get through this tutorial here .
I started by running the code in a file here:
import socket
HOST, PORT = '', 8888
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
print('Serving HTTP on port %s ...' % PORT)
while True:
client_connection, client_address = listen_socket.accept()
request = client_connection.recv(1024)
print(request.decode('utf-8'))
http_response = """\
HTTP/1.1 200 OK
Hello, World!
"""
client_connection.sendall(bytes(http_response, 'utf-8'))
client_connection.close()
then in the next part, it tells me to enter this line on the same computer.
$ telnet localhost 8888
I have webserver1.py running on a different cmd window (in windows). when I run this line though I get a blank screen instead of
$ telnet localhost 8888
Trying 127.0.0.1 …
Connected to localhost.
like I'm supposed to. Does anyone know why? How to fix it? I tried googling telnet localhost 8888 to no avail, I couldn't find a situation where this happened before.
so uh... unless there's an http daemon running/listening on that port, which couldn't happen anyway because of how ports typically work (but not always), that's actually about as far as that exercise will go.
The result you had was correct, based on the output you got after running telnet from another cmd session while that python script was running in the background. However, the windows oobe version of telnet is weaksauce. Using it to send additional commands to communicate with the server once a successful connection is established is kinda booty.
The script invokes the python interpreter (shoulda used #!/usr/bin/env python... just saying) and uses a few objects from the socket lib to open a socket on port 8888 on the localhost (the computer you're currently logged into).
That's it, nothing more. I ran through the exercise too, and gisted it # https://gist.github.com/mackmoe/09de098b3df5c45adf7a17b764a1eec4
Just my 2 cents here:
If you want to setup a server for the experience (and for free), just grab virtualbox, a linux server iso and use one of digital ocean's walkthroughs. Like the one # https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-16-04
Hope That Helps Friend!
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.