How to connect client in a internet to the server - python

I made a simple chat room. But I can't connect clients who joined through internet. I know I'm using local network to this program. But I researched how to connect my server to the internet. I used my Dynamic public IP and port forwarded using my router, but It didn't work. And I used ngrok, but it also didn't work. How can I solve this problem.
This is a part of my program.
IP_Address = 'IP'
Address = (IP_Address,PORT)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(Address) # Bind IP address and Port to this socket.
When I used my public addressit shows this error.
Traceback (most recent call last):
File "Documents/Projects/Python/server.py", line 13, in <module>
server.bind(Address) # Bind IP address and Port to this socket.
OSError: [Errno 99] Cannot assign requested address

Use server.bind(('',port)) or server.bind(('0.0.0.0',port)). Both mean "bind to all interfaces".
If you want to bind to a specific interface, use your local IP, not the public one. Use ipconfig from the console to see your IP address.
On the router, forward the port to your local IP. Clients on the internet connect to your public IP and port.

I think the best way to solve this problem is using a Cloud Application Platform to run the server program.

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)

Google DNS Server

I wanted to get my private IP address using Python, so I found a snippet of code that does it.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
Here 8.8.8.8 is address for Google DNS server. Now whenever we hit an external site, we are only represented by our public IP address, so how is Google DNS able to find my Private IP address ? Moreover this was working even when my Internet connection was off.
I wanted to get my private IP address using Python, so I found a snippet of code that does it. ... so how is Google DNS able to find my Private IP address ?
This snippet of code does not do what you expect it to do. All it reports is the local IP address from an UDP socket "connecting" to 8.8.8.8. This information does not come from Google, it comes from your local operating system which of course knows what its local IP address is. In fact, you could connect to any other external IP address and you'll get the same information back.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
Apart from that the code is wrong too. It does not connect to the DNS server - the DNS server would be port 53 and not port 80 as you use here.

Python 3 - Hosting a server

Basically, I'm making a Game Server for my Python text-based game. What I want is to let each player make his own local server and/or public server but I don't seem to get it. I've tried this:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = input("Enter an IP: ")
port = 10922
serversocket.bind((host, port))
But whenever I'm running it and type my own external IP, it throws me this error:
"OSError: [WinError 10049] The requested address is not valid in its context"
Edit: To add to this, it only works with host = "127.0.0.1" but the server isn't public that way.
Can anyone help with this?
The reason it throws this error is because you are binding to an unknown address hence the error.
To bind the socket to your IP, do: socket.gethostbyname(socket.gethostname()) in the place of the address.
socket.gethostname() gets the hostname of the computer e.g. DANS_PC
socket.gethostbyname() looks up the IP of the hostname that is given in the parameters.
To make the server public however, do the same but port forward your computers IP address in your router settings.

Python: Connect using sockets via external IP

Today, I have made my very first sockets program - I made a client and a server that message each other (kind of like a chat) using sockets. When using the internal IP as 'host', The connection is established, otherwise using the external IP, no connection is established.
Edit 1:
#Client
s = socket.socket()
host = '123.123.123.123'
port = 9999
s.connect((host, port))
#Server
host = ''
port = 9999
s = socket.socket()
s.bind((host, port))
s.listen(5)
connection, address = s.accept()
How will this work properly with, for example, a laptop? Since your IP changes each time you switch Wifi, how would I be able to create a program that would permanently work with this specific laptop?
I understand that I have to port-forward the specific port to a specific internal machine such as 192.168.0.5. but what if I'm using a laptop and I don't have access to the WIFI router. I wouldn't have access to every router a laptop uses.
I want the code to be permanently compatible.
Use DynDNS.com or NoIP.com portal. You install program on laptop which check your IP frequencly and sends current IP to portal which assigns this IP to your address like "my_laptop.noip.com". Then people can access your laptop using "my_laptop.noip.com" instead of IP address.
You always assign socket to IP of local network card (NIC) like WiFi. You can't assing to external IP. You have to config your router so requests to external IP:port will be send to your local IP:port. Of course Internet Provider routers can block your ports and it will not work.

library socket: open port

I have try to create a little online game with python but I face a problem.
I have no problem as long as I work in local (same computer or private IP adresse) but the socket can't connect if i use an IP.
Server:
import socket
co_prin = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
co_prin.bind(('', 9000))
co_prin.listen(10)
co,info=co_prin.accept()
print('connexion recu')
co.close()
co_prin.close()
Client:
import socket
co_serv=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
adresse='81.56.76.61'
co_serv.connect((adresse, 9000))
print("Connecté.")
co_serv.close()
If I change adresse by 'localhost' there is no problem.
One tell me that the reason was python can't open the port. I would like to know if there is a solution to solve or bypass the problem easy to use for other user. (I can always create a local network with hamachi or open the port manually but it's wouldn't be easy to share my programm).
Edit, the error in the client code: Traceback (most recent call last):
File "", line 5, in
co_serv.connect((adresse, 9000))
socket.error: [Errno 10061] No connection could be made because the target machine actively refused it
You are not using your actual computer IP. You are using your public IP address.
Open cmd/command.com and type in the command: ipconfig.
You will there see a totally different IP (IPv4/IPv6 address):
Most likely you want this (do this for yourself!):
Then, if you want people outside your network want to access your computer you must port forward the port to your network IP address from your router.
If you are just experimenting with python, it's best to use 127.0.0.1 or localhost as IP-address.

Categories