I am trying to send message from Raspberry Pi (Ubuntu 20) to Laptop (Virtualbox Ubuntu 20) via UDP socket. So I am using simple code from https://wiki.python.org/moin/UdpCommunication
Sending (from Raspberry Pi)
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = b"Hello, World!"
print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)
print("message: %s" % MESSAGE)
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
Receiving (from laptop)
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print("received message: %s" % data)
I tried UDP_IP = "0.0.0.0" in both ends.
I tried Ip address of my laptop at RPI end.
I tried both machine's IP address at both ends.
I tried sock.bind(("", UDP_PORT)) to bind all.
I tried adding the UDP port number in firewall settings.
I checked multiple questions from this forum related to this.
Still, I cannot get any packets at the laptop receiving side. I do not know what is wrong.
Please advise.
The problem may be in the IP address because you are using the IP '127.0.0.1' (localhost) to reach an outside device. Please find out the IPs of your devices, try using ifconfig Linux command. Also, check that nothing is blocking your connection.
Consider that for socket.bind(address) you can use '0.0.0.0' and for socket.sendto(bytes, address) you should use the IP of the device you want to send to.
I recommend you to download a program called Hercules, with this program you can create a UDP peer to figure out what is not working properly. For example, you could use python in one side and Hercules in the other to rule out mistakes in one side of the code execution, you could also try two Hercules connections and see if you can establish communication in which case the problem is most likely related to the code execution, in the other hand if you can not establish a connection between the two Hercules UDP peers the problem is most likely with the devices or the network itself.
If you are using a static IP on the RPi, you need to add a static route:
sudo ip route add 236.0.0.0/8 dev eth0
Make sure the port you are using have UDP enabled in windows 10.
To open any UDP ports, you can do the following:
Go to Control Panel> System and Security and Windows Firewall.
Advanced settings > right-click Inbound Rules and select New Rule.
Add the port(s) you want to open and click Next.
Select UDP protocol and the port(s) number(s) into the next window
and click Next.
Select Allow the connection and hit Next.
Select the network type and click Next.
Give a name for the rule and click Finish.
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)
[WinError 10061] and [WinError 10060]. These are the errors im getting when i send a client app to my friend. Remotely it just doesn't work. Locally it works fine. Can i get a full explanation step by step please cause i couldn't find any soulution and i'm getting mad.
SERVER:
import socket as s
HOST = 'ppp.ppp.p.ppp'
PORT = 33000
server_socket = s.socket(s.AF_INET, s.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen()
while True:
client_socket, address = server_socket.accept()
print(f'Connected {address}')
CLIENT:
import socket as s
HOST = 'ppp.ppp.p.ppp'
PORT = 33000
client_socket = s.socket(s.AF_INET, s.SOCK_STREAM)
client_socket.connect((HOST, PORT)) # here is error
PS: CLIENT GETS ERRORS NOT SERVER
welcome to SO. You and your friend are probably not on the same network. Therefore, when sending a connection request, your router (or your friends) does not know to relay the packet to the correct device in it's network. There are multiple things you need to do:
Make sure that the IP is not your local network IP but rather the IP of your router. check on wahtismyip. Use that as the ip. Note that the ip will change every so often.
Then, the difficult part. You need to tell your router (or your friends if the server is in his network) to relay the packets arriving at port 33000 to the server. This is different from device to device, try googling "Port forwarding ".
Hopefully this resolves your issues.
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.
Title says all. I have a client and a server setup, but they only work with localhost. How can I connect to the socket from a different network?
Client
# Echo client program
import socket
print "Client"
HOST = "localhost" # Symbolic name meaning all available interfaces
PORT = 5001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
while True:
data2 = raw_input()
s.sendall(data2)
Server
# Echo server program
import socket
print "Server"
HOST = "" # Symbolic name meaning all available interfaces
PORT = 5001 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
print data
if data == "Ping":
print "Pong!"
conn.close()
Check your public ip address using online tools like http://whatismyipaddress.com/
Check your local ip address using ipconfig -a in windows ifconfig in linux.
Now if you are behind a dsl router (generally, you are) these addresses are completely different. So you have to tell your router to send whenever a connection attemp received to a TCP port XXXX , forward it to "My Machine" (called Port Forwarding ). Although port forwarding settings are similar in most routers, there is no standard (Generally under NAT / Port Forwarding menu items on your router web configuration interface ). You may have to search instructions for your specific model.It's a good idea to set your computer to use a static ip address before port forwarding.Otherwise, the settings will be invalid if your computer is assigned another IP adress via DHCP.
If port forwarding is successful, now you only have to set your client application to connect to your public ip address. In your specific situation it's HOST = "X.X.X.X" in your client source code. Check if port forwarding works with a socket tester application you downloaded from somewhere. ( Don't test it with your experimental code, use an application you are sure that it's working). All did not work, check out the note below. It's the last resort ,though.
Note : Some ISP's put their clients behind an extra firewall for security. A simple method to detect if this is the situation is , your Wan ip address you see in your router web interface will be different from what you see in online tools like whatsmyip. In this situation no matter what you do , you will not be able to connect. You have to call your ISP and tell them to disable firewall for your connection . You may have some difficulties to explain them what you are talking about :).
So you have a basic understanding of the parts im using, I have:
Arduino Uno
Seeed Studio GPRS Shield v2.0 (http://www.seeedstudio.com/wiki/GPRS_Shield_V2.0)
Ultimate GPS for Adafruit V3.3 (https://www.adafruit.com/products/746?gclid=Cj0KEQjw3-W5BRCymr_7r7SFt8cBEiQAsLtM8qn4SCfVWIvAwW-x9Mu-FLeB6hLmVd0PAPVU8IAXXPgaAtaC8P8HAQ)
Here is my problem:
I have tested the Arduino stacked with the GPRS shield, and it works fine with regards to accessing the internet through TCP, sending SMS, etc.. However, my application requires me to send GPS data from the adafruit GPS to a web server that I have already coded with Django and postgresql. The backend is set up.
I need to send the data from the Uno (client) to my laptop (server), which I coded in python (This is just to check whether it is creating a connection):
#!/usr/bin/env python
import socket
# import postgres database functions
TCP_IP = '192.168.1.112'
TCP_PORT = 10000
BUFFER_SIZE = 40
server_address = (TCP_IP,TCP_PORT)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created.'
# Bind socket to TCP server and port
try:
s.bind(server_address)
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket Bind Complete.'
# Start Listening on socket
s.listen(1) # Puts socket into server mode
print 'Listening on port: ', TCP_PORT
# Now Keep Talking with the client
while (1):
# Wait to accept a connection
conn, addr = s.accept() # Wait for incoming connection with accept()
print 'Connection address:', addr
data = conn.recv(BUFFER_SIZE)
if not data: break
print "recieved data: data", data
conn.send(data) #echo
conn.close()
I dont think there is a problem with this. From this I will post data to my postgreSQL database. However, When I try to use AT commands on the SIM900 module to connect to the server using port 10000, I cannot connect:
AT+CIPSHUT
SHUT OK
AT+CGATT?
+CGATT: 1
OK
AT+CIPMUX=0
OK
AT+CSTT="fast.t-mobile.com","",""
OK
AT+CIICR
OK
AT+CIFSR
6.60.94.49
AT+CIPSTART="TCP","192.168.1.112,"10000"
OK
STATE: TCP CLOSED
CONNECT FAIL
I have tried connecting through TCP and replaced the AT+CIPSTART line with the below statement and it worked, so I know TCP works:
AT+CIPSTART="TCP","www.vishnusharma.com", "80"
Is the IP i'm using wrong? I'm new to this, but if it makes a difference, im using Ubuntu 16.04 partitioned on my Mac OSX. I have also checked the APN for T-mobile and it seems fine.
Any help would be greatly appreciated. Thank You!
The IP you're using is inside a NAT since it starts with 192.168. Unless you have a private apn with the mobile operator you're using, you won't be able to reach your Ubuntu from a public IP. Your ISP gives you a public IP address which ir administrated by your router, so if you want this to work, you'll have to do a port forwarding from your router to your Ubuntu.
To do the port forwarding you have to get in the router's configuration page (Typically 192.168.1.1 but depends on the model) an there you'll have to redirect the port XXX to 192.168.1.112:10000. After that you have to obtain your public IP (curl ifconfig.co) and use it to access from the SIM900.
First of all as a suggestion, you can combine the two shields by using SIM908 (unless you are getting more precision on your GPS shield). Since your TCP connection is working, I bet that the port 10000 on your ubuntu is blocked by the firewall. You can first try to turn off your firewall and see if it works. If it did not worked its something else. If it worked, turn on your firewall and then unblock the tcp port using the following command:
sudo ufw allow 10000/tcp