Weird network behaviors with UDP sockets and python - python

I made some python script and ran it both on my computer and some distant shell (some website that provides shell access).
I'm using threads, pipes and UDP sockets to transfer data in a P2P fashion, so each script can both receive and send through the same socket. To test if this works, I open one terminal on my computer and one other terminal with ssh, connected to my shell. I make sure the script is the same on both machines, and feed it with an ip address.
Here is the script: http://codepad.org/V9Q1KcDT
(I don't know if I should paste it directly here or not)
My problem is this: strings I send seems to land something 20% of the time, sometimes often, sometimes not, and it seems to be random...
What am I doing wrong ?
Are UDP so unreliable ?
Are python thread+pipe+socket too slow ?
Could it be some kind of network problem with my shell provider ?
Is my program flawed ?
Are pipes a good solution to communicate with threads ?
I have no problem not using a shell and I have not tried, but it's useful for testing purposes.
BTW if i'm behing a router, how does the router knows where to send the packet if I'm not the only computer connected ? (I tried when I was the only one, it behaved identically).

User Datagram Protocol(UDP) could easily stand for Unreliable Datagram Protocol. UDP provides no guarantees regarding delivery so if you need reliability you have to implement it yourself by resending messages.
That said, threading and multiprocessing and remote machines and networks are a lot of variables to diagnose at once. I'd advise you to step back and try to boil the problem down to something simpler.
For instance:
first try TCP instead of UDP
instead of threads, run 2 processes (one doing nit_send, one doing nit_recv)
run them both on your local machine (use localhost: 127.0.0.1)
Once you have this basic test working then add features back in. For instance, switch to UDP. Once you've got your UDP issues sorted out locally try introducing remote machines or threads, etc.
Regarding the router question all machines connected to your router are most likely NAT'd so they all appear to have the same IP address (the IP address of your router) to machines on the internet. Look into NAT and port-forwarding if you want to route traffic to a specific machine on your local subnet.

Related

What would be the best way to transmit data from one python script to another, without them being on the same computer?

I am attempting to create a basic chatroom in python, and I would like to know how I could transmit data from one script to another, preferably without using google drive. If needed to, I could create a webserver on Replit, but I don't do well with HTML or PHP.
Side note: I can't port forward, as my google wifi doesn't accept any level of port forwarding.
I would send messages of about 50 characters every couple seconds
Since you mention port forwarding, I assume you want two chat clients that run on different local networks to talk to each other, for example your own and the chat client of a friend in a remote location, over the internet.
If you (or your counterpart) cannot set up port forwarding, then direct communication between the script on your computer and theirs is hard, if not impossible. The solution is to set up a third computer or service on the internet that can be reached by both clients and use it for relaying messages between them.
A network is typically protected by a firewall of sorts and will typically be behind a router that performs network address translation (NAT) to help multiple devices on a network to simultaneously access services on the internet, whilst all using the same IP address on the internet. Port forwarding fits into that by connecting a specific port from the outside directly to a port on a machine on the inside - without that, an outside computer might be able to reach your IP address, but they could never connect to a computer or program on the inside of the network, as the router wouldn't know what computer to contact, also the firewall might disallow the connection to begin with.
But if your computer on the inside establishes a connection with an accessible server on the internet, expecting a response, that creates a temporary conduit through the router and firewall that can be used by the server to send messages (look up 'hole punching' for more information). And if both computers do this, the server can relay message between both clients. Only the server then needs to run in an environment that doesn't have firewall restrictions or NAT that prevent this.
You could write a simple Python server, that accepts incoming connections and can send several responses and a simple client that connects to it, identifying itself and joining a chatroom, or having a direct conversation with another connected client. There are many techniques that would allow you to do this, but I think web sockets might be a good starting point, as long as you don't plan to do advanced fast or high volume stuff that would require something like a UDP connection.
A library like websockets could be a good starting point, but you may want to start out by figuring out where you would have this service hosted first, since there may be limitations on what you're able and allowed to do.
Also, if all you're looking to do is send simple messages, you may want to stay away from writing your own server an protocols at all - have a look around for open source message servers written in a language you are comfortable with, or that just work out of the box without any development, in which case the language doesn't even really matter, as long as you can connect to it and exchange messages from Python.

Raw TCP Listen Socket on Cloud or Web Server

I have hardware that connects to raw TCP socket on any given IP and port combination. It then continually sends characters. The following piece of Python code may give you an idea of what the hardware does.
import socket
serverIP = '*server IP or domain*'
serverPort = 60000
Sock = socket(AF_INET, SOCK_STREAM)
Sock.connect((serverIP, serverPort))
while (1):
f = open ("send-data.txt","r")
while 1:
c = f.readline()
if not c:
break
Sock.send(c + '\n')
Sock.shutdown(0)
Sock.close()
When this code is run it exactly behaves like my hardware system. The send-data.txt file contains characters similar to what hardware sends.
I have written a socket server in Python using SocketServer library. It allows connections, receives character stream, and stores it into a local (newly created) file. Currently, I am running this code on my system, as localhost and it works. I would like to serve these files through a webpage.
I want to be able to do the same on remote server. As you can see, my hardware limits me to use only raw TCP sockets. From what I understand, I'll need low-level access to the server machine like IaaS. I tried pythonanywhere, but I guess they don't allow simple python sockets. Heroku also requires you to write a web app, and I don't know how to go about that or whether it'll work with my hardware.
What hosting/Cloud solution out there could act as above-mentioned socket server and also as HTTP server which would later serve these files and webpages.
If I understand your question correctly, you'd like to know which affordable hosting solution would allow you to communicate via arbitrary TCP sockets.
The answer is simple: Pretty much any VPS (Virtual Private Server) company or IaaS provider. Since you tagged your question with Amazon-EC2, yes they do too, but the learning curve to get your first instance running and the security groups (read: firewall rules, which live outside your VM) configured, is rather steep. That said, you do have a so-called "Free Tier" there for one year, which enables you to try out most of their services free-of-charge.
Other providers might be more suitable. (I'm not sure if it's allowed to suggest providers here, but you could for example look at Linode or Rackspace Cloud; they offer much less flexibility than EC2, but it's a whole lot easier to get started.)
As with any IaaS option, it would be beneficial to know Linux, networking and some security basics (at the very least) as you will be solely responsible for the things you create.
Talking about security...
If that piece of code you posted has a similarly rudimentary receiving end, you're setting yourself up for trouble as soon as it's out there in public, as the communication is done in plain text [*] and doesn't seem to require any kind of authentication. Anybody could probably telnet to the receiving end and just inject some lines of text?
(That's exactly why considerably sane PaaS providers often don't let you communicate over arbitrary ports and sockets :-) )
[*] I am guessing that, because you use readline. If any encryption was involved, you'd likely write/read in chunks of bytes.

Python Web Service vs Socket programming Client/Server Design

I need some help, i am on early design stage of a client server software and i don't know which of the 2 options (Web Service or Socket programming) are the right one for my software.
All programming is in python.
The layout:
PC will need to run a server service - this server will get commands from the local computer and will send them to the MiniPC.
MiniPC will need to run a client service - when it identify a command (method) he will go to hardware (connection by serial,usb.....), do something and return to the miniPC with result.
MiniPC get the Hardware result and sends it to the Logging server and to the Main PC
Notes:
PC can controls several MiniPC.
The amount of data in one hardware response can be up to 10Kb.
Commands from PC to MiniPC are small (strings)
Logging data can be up to 10Kb.
Questios:
What is you recomendation for protocol Web (http) or Socket programming?
Do you have any suggestions for the design?
You should be able to use socket programming for this. Setup a socket server at the PC and a client at MiniPC devices. The clients would wait for input (read from socket) from the PC and then send back the output that they would get back from hardware. In terms of design, I see two things. First, the socket server can run a select() to handle multiple clients. Second, you probably want to bump up the SO_SNDBUF socket option for MiniPC sockets and SO_RCVBUF for the server at PC to multiples of 10Kb. What is your argument for considering Web?
I'have done a similar project with ARM-based controllers instead on BeagleBone : feel free to ask me questions by commentaries.
Firstly, technically your BeagleBones are servers - since they ran a daemon service which is event triggered - and PC are clients. (but it is just pendantry)
Secondly, due to the limitations of embedded devices, I was not able to have an efficient Web server running on servers, so the choice was simple. I would advise you to stick with socket programming, but adding network services such as DCHP , support of TCP/UDP/UDP multicast, ping, echo, ...
Finally, the important question in terms of performance is the following :
what's the physical layer of communication ?
Ethernet ? Wifi ? Bluetooth/ZigBee ? I2C/CAN/... ?
I will guess it's Ethernet : IEEE 802.11 protocol doesn't scale well because of CSMA ( see here http://fr.wikipedia.org/wiki/CSMA ). If you want to have several devices (dozens), you will need switches/routers to encapsulate sub-networks to avoid network congestion.

Decentralized networking in Python - How?

I want to write a Python script that will check the users local network for other instances of the script currently running.
For the purposes of this question, let's say that I'm writing an application that runs solely via the command line, and will just update the screen when another instance of the application is "found" on the local network. Sample output below:
$ python question.py
Thanks for running ThisApp! You are 192.168.1.101.
Found 192.168.1.102 running this application.
Found 192.168.1.104 running this application.
What libraries/projects exist to help facilitate something like this?
One of the ways to do this would be the Application under question is broadcasting UDP packets and your application is receiving that from different nodes and then displaying it. Twisted Networking Framework provides facilities for doing such a job. The documentation provides some simple examples too.
Well, you could write something using the socket module. You would have to have two programs though, a server on the users local computer, and then a client program that would interface with the server. The server would also use the select module to listen for multiple connections. You would then have a client program that sends something to the server when it is run, or whenever you want it to. The server could then print out which connections it is maintaining, including the details such as IP address.
This is documented extremely well at this link, more so than you need but it will explain it to you as it did to me. http://ilab.cs.byu.edu/python/
You can try broadcast UDP, I found some example here: http://vizible.wordpress.com/2009/01/31/python-broadcast-udp/
You can have a server-based solution: a central server where clients register themselves, and query for other clients being registered. A server framework like Twisted can help here.
In a peer-to-peer setting, push technologies like UDP broadcasts can be used, where each client is putting out a heartbeat packet ever so often on the network, for others to receive. Basic modules like socket would help with that.
Alternatively, you could go for a pull approach, where the interesting peer would need to discover the others actively. This is probably the least straight-forward. For one, you need to scan the network, i.e. find out which IPs belong to the local network and go through them. Then you would need to contact each IP in turn. If your program opens a TCP port, you could try to connect to this and find out your program is running there. If you want your program to be completely ignorant of these queries, you might need to open an ssh connection to the remote IP and scan the process list for your program. All this might involve various modules and libraries. One you might want to look at is execnet.

Network Communication program in python

Basically what I'm trying to achieve is a program which allow users to connect to a each other over a network in, essentially, a chat room. What I'm currently struggling with is writing the code so that the users can connect to each other without knowing the IP-address of the computer that the other users are using or knowing the IP-address of a server.
Does anyone know of a way in which I could simply have all of the users scan the IP range of my network in order to find any active 'room' and then give the user a chance to connect to it?
Also, the hope is that there will be no need for a central server to run this from, rather every user will simply be connected to all other user, essentially being the server and client at the same time.
I can give you two suggestions. First of all, UDP packets to the broadcast address of your network will be received by everybody. Secondly, there is a protocol for programs offering certain services to find each other on a local network. That protocol is called mDNS, ZeroConf, or Bonjour.
Using broadcast UDP is likely going to be the faster route. But if I were you, I'd learn how to use ZeroConf instead. It's supported well under IPv6 and already used by several interesting programs such as SubEthaEdit and Gobby.
Here is a link to a nice tutorial for implementing something that speaks ZeroConf in Python.
Another recommendation... If you want to hand roll your own broadcast/multicast UDP code and you can be sure that all of the systems you're on are running a Linux that's newer than 2003 or so, and all the Windows systems are XP or better, you can probably get away with using IPv6. The IPv6 link-local (think same LAN) all hosts multicast address is ff02::1. That's really simple and easy, and it will reach all the other systems on the same LAN. It's much better than having to figure out what your network's broadcast address is with IPv4.

Categories

Resources