Connect to Socket from Outside Local Network - python

I'm trying to get a socket connection between two different terminals. When they are both on the same computer, or on a different computers on the same network (behind my home router), it works fine.
Here is a minimal example of the code I use. On the client side I enter the IP address I get from running ipconfig on the server, it works with both the IPv4 Address and the Temporary IPv6 Address (changing the corresponding flag of course)
SERVER
import socket
ip_address = ""
ipv6 = False # True
PORT = 12345
STREAM = socket.SOCK_STREAM
if ipv6:
FAMILY = socket.AF_INET6
bind_args = (ip_address, PORT, 0, 0)
else:
FAMILY = socket.AF_INET
bind_args = (ip_address, PORT)
server_socket = socket.socket(FAMILY, STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(bind_args)
server_socket.listen()
unsecured_sock, client_address = server_socket.accept()
print("accepted from", client_address)
CLIENT
import socket
ip_address = "Entered from ipconfig or whatsmyip.com run from server"
ipv6 = False # True
PORT = 12345
STREAM = socket.SOCK_STREAM
if ipv6:
FAMILY = socket.AF_INET6
bind_args = (ip_address, PORT, 0, 0)
else:
FAMILY = socket.AF_INET
bind_args = (ip_address, PORT)
sock = socket.socket(FAMILY, STREAM)
sock.connect(bind_args)
print("Connected!")
The problems arise when I take one of the computers out of the home network. As I don't have two standard networks I can access at the same time, I test this by connecting one of the computers to the internet via either the 4G on my phone or through a VPN. In either case, I then use the IP I get from whatsmyip.com ran from the server. I've tried all combinations of IPv4 vs IPv6 and whether the server or the client is behind my home router. In all cases it fails (note, I don't get a IPv6 address when the server is accessing the internet via 4G on my phone). In fact, I can't even ping or tracert the ip address of the server from the client terminal.
I suspect that I'm doing something very basic wrong, but I don't know what. I suspected it was to do with port forwarding, so I tried the following UPnP script
import upnpy
upnp = upnpy.UPnP()
devices = upnp.discover()
device = upnp.get_igd()
service = device.WANIPConn1
service.AddPortMapping(
NewRemoteHost='',
NewExternalPort=12345,
NewProtocol='TCP',
NewInternalPort=12345,
NewInternalClient='192.168.0.136', # Local server IP
NewEnabled=1,
NewPortMappingDescription='Test port mapping entry from UPnPy.',
NewLeaseDuration=600)
print("added new port mapping")
which runs correctly but makes no difference. Am I right in thinking that this should be a non issue for IPv6 anyway? If it makes a difference, the provider for my internet says that my connection is IPv6 and that I do not have a proper IPv4 public address. Considering I want this to be portable and, eventually distributed, I'd rather avoid it be dependent on specific settings not accessible to the user.
Any pointers for a networking noob are most appreciated

Related

Python socket.gethostname

I'm trying to code a small web server in python to catch an HTTP post.
But I'm having an issue with the socket.gethostname part of it
here is my sample code
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind((socket.gethostname(), 8089))
serversocket.listen(1)
while True:
connection, address = serversocket.accept()
buf = connection.recv(164)
print buf
If i change
serversocket.bind((socket.gethostname(), 8089))
to
serversocket.bind(("localhost", 8089))
Everything is fine I can telnet into it, but I need to be able to connect from another web server on the internet so I need to use socket.gethostname but this block my telnet.
You are using a clever trick to get your servers "real" address when potentially several network interfaces are open. serversocket.bind((socket.gethostname(), 8089)) can be broken down to
hostname = socket.gethostname()
dns_resolved_addr = socket.gethostbyname(hostname)
serversocket.bind((dns_resolved_addr, 8089))
You get your local hostname and then ask DNS what it thinks your IP address is, and bind to that. That's the IP address external connections will use so you should use it too.
But it doesn't always work. DNS may not know what your server name is or your server may have a different name in DNS. One example is my home network where I don't have a DNS server and the DHCP addresses handed out by my modem don't appear in a name server anywhere. A similar problem exists if your corporate DHCP doesn't register your hostname with its local DNS.
On my machine, when I go through the steps I get
>>> socket.gethostbyname(socket.gethostname())
'127.0.1.1'
Notice it was 127.0.1.1 ... I think that's some weird Ubuntu thing to keep its routing tables from getting confused. Anyway, one solution is to try to resolve the address and if you don't like it, fall back to a default.
>>> my_ip = socket.gethostbyname(socket.gethostname())
>>> if my_ip.startswith('127.0.'):
... my_ip = '0.0.0.0'
...
>>> my_ip
'0.0.0.0'

Python - Make socket server on Public Internet Protocol

On Python I would like to make a python server on my public IP...
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("Public IP", 80))
s.listen(5)
conn, addr = s.accept()
But once it hits the bind command
error: [Errno 10049] The requested address is not valid in its context
How would I fix this, how would I get other people around the globe to connect to my python server.
You can only bind to an address that's configured on an interface on your local machine. Since you're using the phrase "public IP", I'm assuming that your public IP is only configured on your router, and your computer has a private address on your local network.
Have your program bind to the machine's local IP, or to any IP available (e.g, ("", 80)), then configure port forwarding on your router appropriately.

How to connect two computers on the same network using python

This is the server side program
import socket
s = socket.socket()
host = socket.gethostname()
port = 9077
s.bind((host,port))
s.listen(5)
while True:
c, addr = s.accept()
print("Connection accepted from " + repr(addr[1]))
c.send("Thank you for connecting")
c.close()
This is the client program
import socket
s = socket.socket()
host = socket.gethostname()
port = 9077
s.connect((host, port))
print s.recv(1024)
When i run these two programs on the same computer, it works perfectly.
But when i run the client and server programs in two different computers on the same network, the program doesn't work.
Can anyone please tell me how to send message from one computer to another on the same network.
This is the first time i'm doing any network programming. Any help would be appreciated
Thanks in advance
You are connecting from the client to the client's computer, or well attempting to, because you are using the client's hostname rather than the servers hostname/ip address.
So, to fix this change the line s.connect((host, port)) so that the host points to the servers ip address instead of the client's hostname.
You can find this by looking at your network settings on the server and doing the following:
host = "the ip found from the server's network settings"
host must be edited to the server's ip if the server is not the same computer.

Python network programming(bind to external address)

I am a newbie to python, and just few days back I started trying my hands on network programming(I am a newbie there too)
Now I found a neat client server program which was running quite simply on my computer, but when I replaced the local addresses, and told my friend to run the client script, it just wont respond.
My global I.P address : 120.59.XX.XXX
My Ipv4 address as returned by ipconfig : 192.168.1.2 (I am connected to internet through a router)
My gateway address : 192.168.1.1
Port used : 1060 (I tested this port locally and it wasn't in use)
#server.py
import socket
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
MAX = 65535
PORT = 1060
server.bind(('192.168.1.2', PORT))
print 'Listening at', server.getsockname()
while True:
data, address = server.recvfrom(MAX)
print 'The client at', address, 'says', repr(data)
server.sendto('Your data was %d bytes' % len(data), address)
Client Code :
#client.py
import socket
import sys
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
PORT = 1060
MAX = 65536
client.sendto('Hello Server!', ('120.59.XX.XXX', PORT))
data, address = client.recvfrom(MAX)
print 'The server', address, 'says', repr(data)
I started server.py on my computer and told my friend to start client.py, I allowed incoming connections to python through firewall, also I added 1060 port to windows incoming connections list.
Still it is not responding, and I am unable to decipher why(I have a dynamic IP address, but for the current session it remains constant and hence should work, also 1060 is a well known port and shouldn't be a problem right?)
You need to add a port forwarding rule in your router! something like from port 1060 forward to 192.168.1.2 port 1060.
You need a port-forward on the router, which would forward connections to router's external (global) address on port 1060 to your desktop IP 192.168.1.2 port 1060.

Making Python sockets visible for outside world?

i already have a post which is quite similiar, but i am getting more and more frustrated because it seems nothing is wrong with my network setup. Other software can be seen from the outside (netcat listen servers etc.) but not my scripts.. How can this be??
Note: It works on LAN but not over the internet.
Server:
import socket
host = ''
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print 'Listening..'
conn, addr = s.accept()
print 'is up and running.'
print addr, 'connected.'
s.close()
print 'shut down.'
Client:
import socket
host = '80.xxx.xxx.xxx'
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.close()
Somebody please help me.
Any help is greatly appreciated.
Jake
Edited again to add:
I think you may be missing some basics on socket communication. In order for sockets to work, you need to ensure that the sockets on both your client and server will meet. With your latest revision, your server is now bound to port 63001, but on the local loopback adapter: 127.0.0.1
Computers have multiple network adapters, at least 2: one is the local loopback, which allows you to make network connections to the same machine in a fast, performant manner (for testing, ipc etc), and a network adapter that lets you connect to an actual network. Many computers may have many more adapters (virtual adapters for vlans, wireless vs wired adapters etc), but they will have at least 2.
So in your server application, you need to instruct it to bind the socket to the proper network adapter.
host = ''
port = 63001
bind(host,port)
What this does in python is binds the socket to the loopback adapter (or 127.0.0.1/localhost).
In your client application you have:
host = '80.xxx.xxx.xxx'
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
Now what your client attempts to do is to connect to a socket to port 63001 on 80.xxx.xxx.xxx (which is your wireless internet adapter).
Since your server is listening on your loopback adapter, and your client is trying to connect on your wireless adapter, it's failing, because the two ends don't meet.
So you have two solutions here:
Change the client to connect to localhost by host = 127.0.0.1
Change the server to bind to your internet adapter by changing host = 80.xxx.xxx.xxx
Now the first solution, using localhost, will only work when your server and client are on the same machine. Localhost always points back to itself (hence loopback), no matter what machine you try. So if/when you decide to take your client/server to the internet, you will have to bind to a network adapter that is on the internet.
Edited to add:**
Okay with your latest revision it still won't work because 65535 is the largest post available.
Answer below was to the original revision of the question.
In your code posted, you're listening (bound) on port 63001, but your client application is trying to connect to port 80. Thats why your client can't talk to your server. Your client needs to connect using port 63001 not port 80.
Also, unless you're running an HTTP server (or your python server will handle HTTP requests), you really shouldn't bind to port 80.
In your client code change:
import socket
host = '80.xxx.xxx.xxx'
port = 63001
And in your Server Code:
import socket
host = ''
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), port ))
In your server script you have port = 80, but you don't ever use it. It looks like the server is listening on 63001. And the client is connecting to 80.
If you're going to use 80, make sure you don't have an http server trying to use the port at the same time as well.

Categories

Resources