I am trying to make a simple server/client program pair.
On LAN they work fine, but when i try to connect from the "outside" it says connection refused. I shut down firewalls on both machines but i am still unable to connect, and i double checked the ip.
What am i doing wrong?
Thanks
Jake
Code:
import socket
host = ''
port = 9888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
conn, adrr = s.accept()
conn.send("Hello, world!")
s.close()
Client:
import socket
host = '68.x.x.x'
port = 9888
s = socket.socket(socket.AF_INET, socket_SOCK_STREAM)
s.connect((host,port))
print s.recv(200)
s.close()
You have one of two possible issues.
Erroneous network configuration
Bug(s) in code
The way to debug this is to try and rule one out. If we can get rid of the Code issue then we know it is a network issue.
Get a Socket Server and client that you know works and then try them as standalone programs. inside and outside of the firewall.
Go to this site and download the examples. Change the ports in both the client and the server, compile and run them. First on same machine within network, second from two machines on same network and then server from within and client from outside of network.
How's the argument you're passing to the .bind call for your server socket? That's the single likeliest cause -- e.g. if you're using 192.168.x.y for whatever values of x and y, or 10.x.y.z likewise, that's a local-network address only, not routed by inter-network routers by internet conventions (most routers can be programmed to forward some incoming packets to a specific local-network address, typically depending on ports, but that's very specific to router's brands and models).
Related
So far I have made a VERY basic client/server application that creates a TCP connection. I have a lot of programming experience, just never did this low-level stuff and especially nothing with networks. Note that all the prints are just to help me figuring out what is going on. One of the known issues is that jsonip sometimes gives me an IPv4 and sometimes v6, I don't know why but that doesn't matter for now, just to warn anyone who wants to recreate my code.
Server:
import socket
import requests
port = int(input("Enter port you want to open:\n"))
#todo: add errorhandling
print("Adding socket...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = socket.gethostname()
print(f"Hostname: {hostname}")
ip_address = socket.gethostbyname(hostname)
print(f"Host address: {ip_address}")
r = requests.get(r'http://jsonip.com')
public_ip_address = r.json()['ip']
s.bind((ip_address, port))
print("Is open for connections on IP: "+public_ip_address+" and Port: "+str(port))
s.listen(5)
print("Done initialisation, listening for incoming connections...")
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established")
clientsocket.send(bytes(f"You have connected to server: {hostname}", "utf-8"))
Client:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = input("Enter IP to connect to:\n")
port = int(input("Enter Port to connect to:\n"))
print(f"Connecting to server {ip} ...")
s.connect((ip, port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
On my local machine: Open 20000 in my server.py, it tells me the host is 127.0.1.1, I then enter 127.0.1.1 into my client script and 20000, and they connect. So the Socket has been bound with the 127.0.1.1. (Side question: What is this IP address, is it like the internal IP address of processes in my PC or something? If running ip a on my other machine it is the first one shown of 2)
Using Virtmanager on my machine and running one Linux Server (command line only) and one normal Ubuntu, the server tells me the host is, again, 127.0.1.1 which I don't need to enter into the other VM to know it won't work, what does work however, is getting the IP-address of the Server via ip a, which in this case is 192.168.122.37, and when I enter this IP address into the client, it connects. But in the socket here I bind, again, the 127.0.1.1, so is it arbitrary what I put here? What SHOULD I bind here, the public, the weird or the 192. address?
The first thing I could not get to work was using 2 physical devices. When opening a server on my Linux machine, I cannot connect with my windows machine at all, no matter if I use my public, my 127. or my 192. IP-address. Now my end goal is doing this over the internet so I am walking myself up, describing here the steps I took to try and get where I want to be but here I hit a brick wall where I don't know what is wrong. Am I binding the wrong address on the server, is my router being a problem, is there something else wrong?
I also tried leaving my network using my friends pc a few countries over, but this also just results in a timeout (my theory is that the Router port he is trying to open is closed and I have now idea how I can make the router send data to his PC, which should be not impossible as firefox and every application using internet does it without me having to manually forward every port, I just don't know how). This is my end goal, creating a connection between my friends PC and mine, and this is how far I got (I wouldn't mind skipping the local network if it is not relevant for fixing the global connection problem), so, tl;dr: what did i do wrong, what do i need to bind and what do i need to do for the final result to work?
There are many questions to answer.
Addresses 127.X.X.X are reserved for the loopback interface, most common one is 127.0.0.1. The loopback is a virtual, but important interface and as you have probably guessed, it is usable on the local machine only. You cannot use 127.X.X.X address to make two hosts to communicate with each other.
Addresses 192.168.X.X (and also 10.X.X.X and 172.16-31.X.X.) are reserved for local LANs. They are not valid on the Internet.
You cannot use these addresses to make two hosts to communicate with each other over the public Internet (unless you create a tunnel, an advanced networking topic)
Almost everybody uses them, because we ran out of IPv4 addresses long time ago, they were difficult to get, expensive, etc. Also such hosts are isolated from the Internet, they can be reached only via a router that translates addresses. Such router feature is called NAT. A typical router has one valid Internet address and all connections to the Internet appear as coming from the router. If you contant a service like jsonip.com from a PC, you get your router's address, not your PC's address.
See also: Finding local IP addresses using Python's stdlib
To make your program working, make it to accept connections on all interfaces. See the first example in the socket docs. On Linux, use port numbers >= 1024. Ports < 1024 are reserved, not available to regular users.
Final point is that a firewall may prevent connections to your server. It depends on your system and setup.
I currently have a raspberry pi that is set up as a wifi to ethernet bridge. The raspberry pi acts as an access point to the entire ethernet subnet that I have. The subnet and the network bridge work perfectly but when I try to get my python program on the raspberry pi to listen to requests on the ethernet interface/subnet it doesn't seem to do that. It is set to bind the socket to ('',10000) but it never receives any messages. However, it is able to send messages via sockets to the subnet just fine, just not receive. I think it is listening to the wifi interface rather than the ethernet one but I'm not sure how to specify which interface the socket is suppose to listen to.
here is my receiving code
receive_group = ('',10000)
receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receive.bind(receive_group)
while(True):
data, address = receive.recv(65536)
print(data)
The bind part should be correct. The receive part is wrong because recv only return the (bytes) data, you should use recvfrom to also get the sender address. But this should work:
import socket
receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receive.bind(('', 10000))
while True:
data, address = receive.recvfrom(64)
print(data, address)
I used this code for the send part:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(b'foo', (addr, 10000))
where addr is one of the (reachable) addresses of the receiver, and the receiver could successfully receive data from any of its interfaces.
To get something from socket.recv something must connect to this socket and send something. Are you sure that some program on the network is doing this?
For listening/sniffing to packets and network traffic, better use pyshark.
Turns out it wasn't anything with python. When I created the access point on the pi it created a firewall rule that blocked that port even though I never configured the firewall that way. Adding an exception to that port fixed my problem
I'm trying to run a python socket server on my local network, with this server code:
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((socket.gethostname(), 9876))
serversocket.listen(5)
while True:
c, addr = serversocket.accept()
while True:
data = c.recv(1024).decode()
print(data)
c.send(data.encode())
Then, using netcat on another network machine, I can connect to the server and send text in, and have it mirrored back. However, after about two or three tries, it suddenly drops back out to the command line and no longer accepts any connections. The server side, however acts the same, and appears like it didn't see the last incoming message.
If I try to connect to it with another socket, it does the same thing, but instead throws error 104, and then error 32.
I am completely stumped. I've tried adding threads, and everything else that I can think of. If anyone on has any ideas on why this is happening, or ways to work around it, I'd love to hear. Thanks! I'm using python 3.5.
Thanks!
this code below is working fine between two computers on the same network but it doesn't work between two computers on two different networks and i have tried to use the public IP address
clint
import socket
s = socket.socket()
port = 10000
ip=input("what is ip : ")
s.connect((ip, port))
print (s.recv(1024))
s.close
server
import socket
s = socket.socket()
ip=socket.gethostbyname(socket.gethostname())
print (ip)
port = 10000
s.bind((ip, port))
s.listen(1)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
c.send(bytes([int(1)]))
c.close()
this question have already been asked many times but all the answers i could found is that i have to do " port forwarding " with out any code examples how to do it in some of the answers they say i should download application that will do the port forwarding to me but i don't know how to use it then in my python code ?
Port forwarding is something you do at the router level. For example if the two computers you are trying to connect are behind two different WiFi routers at two different homes then you need to set both WiFi routers in both locations to forward port 10000 (the one you're using) to forward to the internal IP of the computer where your code is running.
Your WiFi router has a public IP (what you're probably using now) and your computers running your python code have local IPs internal to the network that are assigned by the WiFi routers. Port forwarding takes traffic going to the public IP of a router and forwards it internally in the local network to the computer at some local IP that runs your program.
In other words this is not something you will do in your code — this is something you will do in your router's software.
If you are feeling ambitious you can follow this tutorial that removes the need to configure your devices for port forwarding. Assuming you have uPNP capable routers.
https://www.electricmonk.nl/log/2016/07/05/exploring-upnp-with-python/
And there may even be a module that takes all the leg work out.(not checked how it works)
https://pypi.python.org/pypi/UPnP/1.3
I've been struggling with this for a few hours now and really just don't know where to go from here. I've got an arduino uno with a wifi shield connected to a network, and a laptop with Ubuntu connected to the same network. I'm using the arduino Wifi Library to connect to the network.
I can send data to my laptop from the arduino and print it successfully using: sudo nc -l 25565
I am also trying to use the following python code to do the same thing I did with nc which is also being run as sudo just in case:
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 25565
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(1)
(conn,addr) = s.accept()
print 'Connection address: ',addr
while True:
data = conn.recv(BUFFER_SIZE)
if not data: break
print 'received data: ',data
conn.send('ECHO')
conn.close()
s.close()
But it just hangs at (conn,addr) = s.accept(). Using a client python script on the same laptop I can connect to the above server and I can send data to it which the server then prints.
I just have no idea why nc will print from the arduino but the python server script won't, even though it will print from a python client. Could the arduino libraries be failing to follow some standard that python expects? Thanks in advance.
No, the arduino libraries are not "failing to follow some standard".
Your program is binding to the localhost interface, IP address 127.0.0.1. This means that only programs running on the same PC will be able to connect to your Python server.
Try this:
s.bind(('',TCP_PORT))
Reference:
https://docs.python.org/2/library/socket.html :
For IPv4 addresses, two special forms are accepted instead of a host address: the empty string represents INADDR_ANY, and the string '<broadcast>' represents INADDR_BROADCAST. The behavior is not available for IPv6 for backward compatibility, therefore, you may want to avoid these if you intend to support IPv6 with your Python programs.
https://docs.python.org/2/howto/sockets.html#creating-a-socket :
A couple things to notice: we used socket.gethostname() so that the socket would be visible to the outside world. If we had used s.bind(('localhost', 80)) or s.bind(('127.0.0.1', 80)) we would still have a “server” socket, but one that was only visible within the same machine. s.bind(('', 80)) specifies that the socket is reachable by any address the machine happens to have.