How can I send some udp via python to a web domain? - python

So currently I am trying to send udp to a server with a web domain like this
www.example.com/path?stuff=exist
I am currently trying to use socket
and this is is an example of my code
import socket
IPADDR = '64.233.177.139'
that is the ip of google, and not the ip I am currently trying to send to
PORTNUM = 9001
PACKETDATA = '42["message","test"]'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
s.connect((IPADDR, PORTNUM, '/path?stuff=exist'))
s.send(PACKETDATA)`
And I currently get this error
TypeError: getsockaddrarg() takes exactly 2 arguments (3 given)
I am new to using the socket library and did some digging to no avail.
For some more context I just want to send the data in PACKETDATA to the server google.com/path?stuff=exist (not really that url, just an example)
Anything helps, thanks in advance.

Your immediate programming problem is that socket.connect expects to be called with an argument that is a tuple containing exactly two items -- a hostname (or IP address) string and a port number. But this program passes an argument tuple that contains 3 items -- a host address, a port number and the string '/path?stuff=exist'. That's why the error message complains about finding 3 things where only 2 were expected.
If you want to send '/path?stuff=exist' over UDP then you'll have to include it in the data portion of the datagram. You'll also have to come up with some way of making it distinguishable from the PACKETDATA that you're already putting into the datagram body. (That doesn't need to be fancy. You could just insert a space between the path string and the PACKETDATA.)
There might also be a conceptual problem here. A web server only listens for TCP traffic. It does not listen for UDP traffic. So unless you've arranged for your specific server to have some sort of listener accepting datagrams on the target UDP port, nothing at the server side will collect this traffic even after you've figured out how to get Python to send it.

Related

Difference between C# and Python UDP Examples [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
You can find this C# UDP example in various forms in many places.
UdpClient udpc = new UdpClient(55001);
IPEndPoint iep = new System.Net.IPEndPoint(IPAddress.Parse("192.168.1.100"), 55001);
byte[] data = udpc.Receive(ref iep);
string req = Encoding.ASCII.GetString(data);
When I run portqry, I find that it responds to 127.0.0.1, but not 192.168.1.100.
PortQry.exe -n 192.168.1.100 -p udp -e 55001
I tried this also using the raw socket interface. I could only get it to work if I bind to 127.0.0.1 and PortQry the same.
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 55001);
Socket sock = new Socket(ipe.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
byte[] buffer = new byte[1024];
sock.Bind(ipe);
sock.Receive(buffer);
string req = Encoding.ASCII.GetString(buffer);
When I run the Python UDP receiver example using port 192.168.1.100, I find it responds to 192.168.1.100, but not 127.0.0.1.
On another machine, I have a route added so that traffic to 192.168.1.100 goes out to the router and then returns. In wireshark, using the Python server, I see a packet go out to the router and one come back when I PortQry 192.168.1.100. Doing the same with the C# example, the packet does not return.
What is different? The wireless and VPN adapters are off; so, there should only be one interface being used. I would like to have the behavior I'm seeing in Python in C# so I can see the traffic from WinPcap.
I have some additional info. I've tried this with the underlying winsock library using this exact code except to change the IP and port. The problem is the same. I can receive only on the loopback. I've verified the port is being listened to on 192.168.100 using netstat. I've also discovered the python receive example will accept UDP traffic even when I physically disconnect Ethernet and ipconfig shows no IP at all.
Your code doesn't tell the UdpClient what IP address to use. The IPEndPoint you create isn't actually used anywhere. You should use it to listen on that IP:
IPEndPoint iep = new System.Net.IPEndPoint(IPAddress.Parse("192.168.1.100"), 55001);
UdpClient udpc = new UdpClient(iep); // Set the IP and port
iep = ip = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpc.Receive(ref iep); // This returns the remote IP and port in iep
string req = Encoding.ASCII.GetString(data);
This way you receive on a specific host and port and not only on the loopback address.

Get TCP response from server

I have a program (.exe) that gets certain info from a server, and I wanted to be able to get that info from the command line too. I started netcat and listened on the port the program uses to communicate with its target, because I wanted to know what "requests" to make from a script, and I received this over netcat, plain text:
net.tcp://[my ip address]:41012/Lapis.Btouch/ServerInfo
I tried sending exactly that to the target (replacing my IP for its IP) using socket.send() but it wouldn't return anything. What does that mean and how can I get the data?
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('[server ip address]',41012))
while True:
s.send('net.tcp://[server ip address]:41012/Lapis.Btouch/ServerInfo')
response = s.recv(1024)
print response
s.close()
That's the code I'm using to send the request to the target server. It won't return anything, so I think I'm not making the request in the right way. Thanks for any help.
Try capture your network packet on port 41012, via tcpdump or wireshark or ...
Then check:
does your code send the request?
does the response returned to you?
If the answer for question (1) is False, problem is side of you and your machine. so go and solve it (review your code, check your firewall and ...)
If the answer of question (1) is True, but server doesn't send any response (this case often not happened) review your request format (check you URL or test it via browser or ...). also based on the server you connect to, maybe needed to your machine's IP recognized for server (I mean some server only give response to requests, that come from known IP addresses, in this case you need introduce yourself to server (e.g. add your IP to trusted list on server), before sending request)
Last case, if answer of both questions are correct (I guess it's your problem), you most correct your code (response = s.recv(1024)) why do you used 1024 for your response length?. Use correct and accurate parameters.
In python exist several methods for receiving response via socket (from server), search stackoverflow and you can find useful tips and commands. commands like use non-blocking ways, ascync ways and ...

Sending an object over a TCP server network in python

I am currently working on a small project experimenting with different regions of python. I decided to make a multi-client TCP server in python, and wanted to be able to send a "packet" through the server, it be received by the other clients then parsed. However, I get an error if I try to send the packet, saying I must send either bytes or a string, is there a way to convert the object into bytes, then back or send the packet object through the server itself.
## EDIT ##
I have researched into UDP servers, and I do not believe that is what I am looking for, I probably provided too little information. I am creating a small trial game, for me and some friends to mess about on, I need there to be a constant connection to the server, as information is going to be constantly being sent across the network such as location,direction,speech,inventory etc. and I wanted a way to turn the entire Entity class into a byte array then send that and it be turned back into an instance of the Entity class when it was received.
You could use pickle to serialize/deserialize objects to strings and back. https://docs.python.org/2/library/pickle.html
The simplest possible approach would be to send (gzipped?) JSON'd or msgpack'd objects.
For example, using UDP, this could look something like the below code; note that you would want to reuse the socket object rather than instantiating a new one every time.
import socket
import msgpack
def send_object(obj=None, ip, port):
if obj:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(msgpack.dumps(obj), (ip, port))

Is it possible to have a socket listening to two UDP IPs, one that is 127.0.0.1 (same machine) and a different computer at the same time?

An eye-tracking application I use utilizes UDP to send packets of data. I made a python socket on the same computer to listen and dump the data into a .txt file. I already have this much working.
A separate application also written in python (what the eye-tracked subject is seeing) is running on a separate computer. Because the eye-tracking application is continuous and sends unnecessary data, so far I've had to manually parse out the instances when the subject is looking at desired stimuli. I did this based on a manually synchronized start of both the stimuli and eye-tracking applications and then digging through the log file.
What I want to do is have the second computer act as a second UDP client, sending a packet of data to the socket on the eye-tracking computer everytime the subject is looking at stimuli (where a marker is inserted into the .txt file previously mentioned). Is it possible to have a socket listening to two IP addresses at one time?
Here's my socket script:
#GT Pocket client program
import datetime
import socket
now = datetime.datetime.now()
filename = 'C:\gazelog_' + now.strftime("%Y_%m_%d_%H_%M") + '.txt'
UDP_IP = '127.0.0.1' # The remote host (in this case our local computer)
UDP_PORT = 6666 # The same port as used by the GT server by default
sock = socket.socket(socket.AF_INET, #internet
socket.SOCK_DGRAM) #UDP
sock.bind( (UDP_IP, UDP_PORT) )
while True:
data, addr = sock.recvfrom( 1024) #I assume buffer size is 1024 bytes.
print "Received Message:", data
with open(filename, "a") as myfile:
myfile.write(str(data + "\n"))
sock.close()
myfile.close()
EDIT:
#abarnert I was able to bind to the host address on the Ethernet interface and send a message from computer B to computer A, but computer A was no long able to receive packets from itself. When I specified UDP_IP = '0.0.0.0' computer B was no longer able to send data across the Ethernet. When I specified UDP_IP = '' I received the `error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
This have to do with the script I used on the Computer B to send the data:
import socket
UDP_IP = "169.254.35.231" # this was the host address I was able to send through.
UDP_PORT = 6666
MESSAGE = "Start"
print ("UDP target IP:"), UDP_IP
print ("UDP target port:"), UDP_PORT
print ("message:"), MESSAGE
sock = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT) )
I didn't know where (or if at all) I needed to specify INADDR_ANY, so I didn't. But I did try once where import socket.INADDR_ANY but got ImportError: No module named INADDR_ANY
Seems like a simple issue based on your response, so I'm not sure where I'm messing up.
EDIT2: I just reread your answer again and understand why socket.INADDR_ANY doesn't work. Please disregard that part of my previous edit
EDIT3: Okay so the reason that I wasn't picking up data when specifying the host IP was that the application I was collecting data from on Computer A was still specified to send to 127.0.0.1. So I figured it out. I am still curious why 0.0.0.0 didn't work though!
No. A socket can only be bound to a single address at a time.*
If there happens to be a single address that handles both things you want, you can use a single socket to listen to it. In this case, the INADDR_ANY host (0.0.0.0) may be exactly what you're looking for—that will handle any (IPv4) connections on all interfaces, both loopback and otherwise. And even if there is no pre-existing address that does what you want, you may be able to set one up via, e.g., an ipfilter-type interface.
But otherwise, you have to create two sockets. Which means you need to either multiplex with something like select, or create two threads.
In your case, you want to specify a host that can listen to both the local machine, and another machine on the same Ethernet network. You could get your host address on the Ethernet interface and bind that. (Your machine can talk to itself on any of its interfaces.) Usually, getting your address on "whatever interface is the default" works for this too—you'll see code that binds to socket.gethostname() in some places, like the Python Socket Programming HOWTO. But binding to INADDR_ANY is a lot simpler. Unless you want to make sure that machines on certain interfaces can't reach you (which is usually only a problem if you're, e.g., building a server intended to live on a firewall's DMZ), you'll usually want to use INADDR_ANY.
Finally, how do you bind to INADDR_ANY? The short answer is: just use UDP_IP = '', or UDP_IP = '0.0.0.0' if you want to be more explicit. Anyone who understands sockets, even if they don't know any Python, will understand what '0.0.0.0' means in server code.(You may wonder why Python doesn't have a constant for this in the socket module, especially when even lower-level languages like C do. The answer is that it does, but it's not really usable.**)
* Note that being bound to a single address doesn't mean you can only receive packets from a single address; it means you can receive packets from all networks where that single address is reachable. For example, if your machine has a LAN connection, where your address is 10.0.0.100, and a WAN connection, where your address is 8.9.10.11, if you bind 10.0.0.100, you can receive packets from other LAN clients like 10.0.0.201 and 10.0.0.202. But you can't receive packets from WAN clients like 9.10.11.12 as 10.0.0.100.
** In the low-level sockets API, dotted-string addresses like '0.0.0.0' are converted to 32-bit integers like 0. Python sometimes represents those integers as ints, and sometimes as 4-byte buffers like b'\0\0\0\0'. Depending on your platform and version, the socket.INADDR_ANY constant can be either 0 or b'\0\0\0\0'. The bind method will not take 0, and may not take b'\0\0\0\0'. And you can't convert to '0.0.0.0' without first checking which form you have, then calling the right functions on it. This is ugly. That's why it's easier to just use '0.0.0.0'.
I believe you can bind a raw socket to an entire interface, but you appear to be using two different interfaces.
It's probably best to use two sockets with select().

Sockets: Simulate multiple clients in python using one machine/NIC

I am trying to write a python program that will spawn multiple clients to speak to one server on the network. My question is what do I need to do to simulate different IP addresses for each client?
I am using MAC OSX Lion right now with Python 2.6.
I have already developed the server side that can accept multiple sockets. I want to avoid having a machine for each client. Any tips/hints for a newbie would be appreciated.
Even though this is an old question, it still appears in google...
As already mentioned, basically it will take the IP the connection is received from and assigns the next available port... So with a standard socket.. you will end up with a bunch of connections from the same IP with varying ports.
Personally to me its easier to create a client script that will generate the amount of clients you need (i'm using 1000+ clients from a single python script)..
Once you have the clients generated, have the script generate a IP for each of the clients.. If your handling your connection objects correctly.. You can always refer back to which client you want..
So in the end, you have all the clients coming from the same machine or another on the network but you simply have variable with a random/generated IP address which you can test with.. It takes only a few lines to use the generated IP address as a reference to your socket object.
If you are wanting to work with something IP specific like only allow a connection from a particular subnet.. Simply generate the fake IP address at the time of the connection and use it as if it was the real one.
If you are just wanting to have multiple clients, no need to generate a IP address at all as everything is a different port.
Extract for example purpose:
for i in xrange(1, self.iCount + 1):
if len(self.objClients) >= self.iCount:
break
#Generate a uid ... sID = xxxxxx+i
if sID not in self.objClients:
oPosData = []
self.objClients[i] = {"id":sID, "current":0, "connected":True}
for oT in self.objClients:
try:
self.objClients[oT]['socket'] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.objClients[oT]['socket'].connect((self.ServerIP, self.ServerPort))
self.objClients[oT]['timer'] = time.time() + randint(0, 10)
http://docs.python.org/library/socket.html#socket.create_connection
If supplied, source_address must be a 2-tuple (host, port) for the socket to bind to as its source address before connecting.
I think that should do it.

Categories

Resources