Socket Programming - How to connect a remote address - python

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.

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)

Why is my client only working on my computer but not on any other computer

I am currently trying to learn how servers and clients work by making a trojan using python and sockets import, my client and server work perfectly on my computer but the moment I send the client to my other laptop the server does not connect. This happens even when i am on the same wifi network.
Server:
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ''
port = 1234
server.bind((host, port))
server.listen(5)
run = True
client, addr = server.accept()
print('Got connection from',addr)
while run:
try:
data = input('>>>')
client.send(data.encode('UTF-8'))
msg = client.recv(1024)
print(msg.decode('UTF-8'))
except ConnectionResetError:
print('Client lost server connection')
print('Trying to connect . . .')
client, addr = server.accept()
print('Got connection from',addr)
Client:
import socket
import os
server = socket.socket()
host = '127.0.0.1'
port = 1234
run = True
server.connect((host,port))
while run:
msg = server.recv(1024)
os.popen(msg.decode('UTF-8'))
server.send('Client online . . .'.encode('UTF-8'))
Your client is connecting to IP 127.0.0.1 (the IPv4 loopback address), which will work only when the server is on the same machine as the client.
When the client and server are on different machines, but still on the same LAN network, the client needs to connect to the server's LAN IP instead. Use netstat or similar tool on the server machine to find its LAN IP. Or, simply have your server code print out its local IPs.
When the client is on another network, it needs to connect to the public WAN IP of the server's LAN router, and that router needs to have port forwarding configured on it to route incoming connections from its WAN IP/Port to the server's LAN IP/port. To get the WAN IP, you will have to look at your router's config, or simply query an external site, like https://api.ipify.org, https://api.my-ip.io/ip, etc from a machine on the LAN, like your server.
Update your client to take in the target host/IP from user input, then it will be able to handle all of these scenarios without having to use different code each time.

Connect to python server in different network

My port forward rule
I've created a python TCP server and client which is working fine when I launch both server and client on my computer and when I launch the server and the client on different computers on the same network, however I wanted to make it work when computers are in different networks. I have forwarded my router port 8080 to convert to 8888 in my computer, in fact I have also a rule for the port 80 on my router converting to 8080 on my PC which is the Wamp server, and as the python server is not working I guessed it was from the code but I can't figure it out:
Server:
import socket
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.bind(("127.0.0.1", 8888))
sck.listen(1)
conn, adr = sck.accept()
print('Connected to ', adr)
while 1:
data = conn.recv(1024).decode()
if data and ('over' not in data):
conn.send(data.encode())
continue
break
conn.close()
Client:
import socket
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect(('<my_external_ip>', 8888))
while True:
data = input('Say something: ')
if 'Shut up' in data:
sck.send('over'.encode())
sck.close
break
sck.send(data.encode())
I've made this test:
Started Wamp server and tried to access it by my external ip with chrome (working)
Opened my Python TCP Client and connected to the Wamp server (working)
Turned Wamp off and started my python server with the same port as Wamp, then tried to acess with the python client (not working)
If there's nothing wrong with the TCP Server code why does Wamp work and he don't? Please check the following - Whats the logic behind binding 127.0.0.1 I couldn't understand... Won't that make it only be accessible by my PC?
If that part is ok than at least is something related to the Server code I guess...

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.

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.

Categories