Sending an array over UDP connection - python

I want to send an array using a UDP connection. When I use the sendto function, it complains that it must be a string. Is there any way around this?
Thanks

You must serialize your data (in this case is an array) before sending it. Then in receiver, you will deserialize to get the original data.
You can do it in Python, using pickle or cPickle module:
import cPickle as p
# Sender
data_str = p.dumps(array)
sock.sendto(data_str, addr)
# Receiver
data,addr = sock.recvfrom(buf)
data_origin = p.loads(data)

Related

Python raw socket receive issue

I am using the following python script for raw socket packet transfer. Packet transfer is fine, but I am not able to print the incoming packet from the other end.
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
s.bind(("eth0", 0))
src_addr = "\x54\xbe\xf7\x40\xf5\x82"
dst_addr = "\xff\xff\xff\xff\xff\xff"
payload = ("[("*30)+"Hello"+("]"*30)
checksum = "\x1a\x2b\x3c\x4d"
data = payload+checksum
s.send(dst_addr+src_addr+data)
#for receive function
response=s.recv(4096)
print response
s.close()
There is a third argument to the socket function: protocol. If not given, it's defaulting to 0. For AF_PACKET / SOCK_RAW, the protocol argument specifies what kind of packets you're interested in receiving. The values are documented in the packet(7) man page: http://man7.org/linux/man-pages/man7/packet.7.html
I don't think the values are actually defined anywhere in the core python2 modules. Some of them can be found in scapy (http://www.secdev.org/projects/scapy/), or you can just hunt up the linux header file where they are defined (/usr/include/linux/if_ether.h).
So, to fix this, change your code to:
from socket import socket, AF_PACKET, SOCK_RAW, htons
ETH_P_ALL = 3
ETH_P_IP = 0x800 # Alternatively using this will receive the next IP packet
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
...
Other comments on your code:
As written, the packet you're sending is unlikely to be comprehensible by anyone. You've got a dst and src MAC address, but then you're not providing an EtherType. Instead the first "[(" will be seen as the EtherType. That probably won't make sense to any receiver of the packet so it will just be discarded.
Also, you should understand that with a raw socket, you're going to receive the next packet of the type you've specified in the protocol. That isn't necessarily (and in fact probably won't be) a response to the packet you just sent.
Thanks everyone now I am able receive the packet with the following the script. But still I am facing issue with printing multiple response packets(While doing in loop).
from socket import socket, AF_PACKET, SOCK_RAW, htons
from struct import *
import select
import time
ETH_P_ALL = 3
ETH_P_IP = 0x800
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
s.bind(("eth0", 0))
src_addr = "\x54\xbe\xf7\x40\xf7\x82"
dst_addr = "\xff\xff\xff\xff\xff\xff"
l = "\x00\x21"
ethertype = "\x08\x01"
a ="\x00\x10\x00\x10\x00\x10"
b = "\x00\x11\x00\x11\x00\x11"
payload = ethertype + l + a + b
for i in range(5):
time.sleep(5)
s.send(dst_addr+src_addr+ payload)
message=s.recv(4096)
print message

Is there a way to use socket.recv() to retrieve all information?

I am connecting to a server and receiving the data, but I am new to python and networks so I have only been using recv(x bits) the issue is that it is not a constant number so we either receive too few or too much information.
import socket
import sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sa = ('ip.address', portnumber)
sock.connect(sa)
data = sock.recv()
print data
sock.close()
Is there a way to just receive the information without it looping? Or do you need to know the size beforehand? Thanks.

Python Sockets - Using Coordinates getPos

Basically trying to use client to send coordinates of a character on the screen and then broadcast that to the other client so it draws the character on the screen.
Yet i'm getting the following errors:
Client Side: s.send((y))
Server Side: ValueError: invalid literal for long() with base 10
Client Code that i get error on:
def updatecoords(task):
s.send(name)
print 'Name sent...'
def updatepos(task):
y = format(Cat.getPos())
s.send((y))
print 'Position sent'
return Task.cont
def readServer(task):
try:
data = s.recv(1024)
print data
except:
print 'no data received'
return Task.cont
Server Code that i get error on:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST,PORT))
server_socket.listen(1)
conn, addr = server_socket.accept()
print('Someone connected.He :%s%addr')
while True:
data = conn.recv(1024)
if not data:
break
data = pickle.loads(data) # Or json.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
You are trying to unpickle the received data:
data = pickle.loads(data)
But you are not pickling the data before sending it:
y = format(Cat.getPos())
s.send((y))
Also you have to decide which serialization protocol you wan't to use because pickle and json are not compatible and this comment:
# Or json.loads(data)
suggests that you think both pickle and json should be able to deserialize received data.
So instead of using format you should make your client function similar to this:
def updatepos(task):
y = pickle.dumps(Cat.getPos())
s.sendall(y)
print 'Position sent'
But still this server code:
data = pickle.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
will work only under two conditions:
- class Cat is imported on server side, otherwise pickle.loads will throw UnpicklingError since pickle protocol preserves class name and unpickling restores the object of class Cat but it can't be done if definition of this class is unavailable
- Cat.getPos() returns a dict (or dict-like object) with keys message_id and message, otherwise format(**data) will throw ValueError if data can't be used as dict or KeyError if one of the mentioned keys is missing in dict
You should also notice that I've replaced s.send((y)) with s.sendall(y) since the first one doesn't guarantee that all data will be sent as documentation says https://docs.python.org/2/library/socket.html#socket.socket.send
I've also dropped additional brackets around y - this doesn't change anything but they are not needed.
As you have posted only part of your code, I was only able to resolve issues present in the posted code sample.

Client and Server unable to exchange data python

I'm using python 3.3.this is Server.py.Everything is fine both server and client are able to connect
something might be wrong in here 'tcpcli.send('[%s]%s'%(bytes(ctime(),'utf-8'),data))'.help me out
from socket import *
from time import ctime
HOST=''
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
tcp=socket(AF_INET,SOCK_STREAM)
tcp.bind(ADDR)
tcp.listen(5)
while True:
print('waiting for connection')
tcpcli,addr=tcp.accept()
print('...connected from:',addr)
while True:
data=tcpcli.recv(BUFSIZ)
if not data:
break
tcpcli.send('[%s]%s'%(bytes(ctime(),'utf-8'),data))
tcpcli.close()
tcp.close()
This is CLient.py
from socket import *
HOST='127.0.0.1'
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
tcpcli=socket(AF_INET,SOCK_STREAM)
tcpcli.connect(ADDR)
while True:
data=input('>')
if not data:
break
tcpcli.send(data)
data=tcpcli.recv(BUFSIZ)
if not data:
break
print (data.decode('utf-8'))
tcpcli.close()
When i'm running both they are working fine except I'm unable to send any data from client.
I'm getting this error message.
tcpcli.send(data)
TypeError: 'str' does not support the buffer interface
You are using Python3. This means that, when using the CLI, input() will return a str object (equivalent to python2 unicode). It contains an internal representation of the unicode codepoints of the characters you entered. To send the data over a byte stream interface (such as pipes, sockets, …), you have to convert it to a bytes object. This is easily done by picking an encoding, such as UTF-8, and doing something like this:
data_raw = data.encode("utf-8")
tcpcli.send(data_raw)
You will have to adapt your servers code similarily, by first decoding the data you received from the client and reencoding it after you did string operations on it:
data_decoded = data.decode("utf-8")
reply = '[%s]%s' % (ctime(), data_decoded)
tcpcli.send(reply.encode("utf-8"))
You are building unicode strings, not byte strings, and the socket interface doesn't support unicode strings. You'll need to encode the result of the string interpolation:
tcpcli.send(bytes('[%s]%s' % (ctime(),data), 'utf-8'))

Sending and Receiving arrays via Sockets

Is it possible to send an array through UDP Sockets using Python? I am using Python 2.5 and trying to send a simple array but it's not working. It can send the array successfully but when I try to print it with an item of the array the program crashes. I'm not sure what the error is as I take the precaution of converting the data into an array but it's not working. Hope I explained the problem as clearly as possible. I would appreciate the help!
# Client program
from socket import *
import numpy
from array import*
# Set the socket parameters
host = "localhost"
port = 21567
buf = 4096
addr = (host,port)
# Create socket
UDPSock = socket(AF_INET,SOCK_DGRAM)
def_msg = "===Enter message to send to server===";
print "\n",def_msg
a = array('i',[1,3,2])
# Send messages
while (1):
data = raw_input('yes or now')
if data!= "yes":
break
else:
if(UDPSock.sendto(a,addr)):
print "Sending message"
# Close socket
UDPSock.close()
# Server program
from socket import *
# Set the socket parameters
host = "localhost"
port = 21567
buf = 4096
addr = (host,port)
# Create socket and bind to address
UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)
# Receive messages
while 1:
data,addr = UDPSock.recvfrom(buf)
L = eval(data)
if not data:
print "Client has exited!"
break
else:
print "\nReceived message '", L[1],"'"
# Close socket
UDPSock.close()
eval is doing something completely different than what you think.
To send data over network, you need to serialize it into an array of bytes, then deserialize it back. In Python, serialization of most objects can be done via pickle module:
if (UDPSock.sendto( pickle.dumps(a), addr)):
Deserialization:
data,addr = UDPSock.recvfrom(buf)
L = pickle.loads(data)
print repr(L) # prints array('i', [1, 3, 2])
I would personally use tostring and fromstring since the built-in serialization methods are many times faster and pickle may not support NaN, Inf and other undefined values.
You're trying to send a python object through a socket, it is normal that it doesn't work, you can't send objects in a socket, objects are not data, they are the representation of some data in a given programming language. You need to "translate" your object to data and re-create the object from the data on the other socket's side. One way to do this would be with the pickle module.
On the client side, you "pickle" the object:
data = pickle.dumps(my_array)
And on the server side, you "unpickle" the received data:
my_array = pickle.loads(received_data)
You could try to pickle the array. Pickle is a python library to en- and decode python objects. It is able to do much more, but it is definitely sufficient to fulfill your task:
on the sender side you pickle the object to a string:
pickled_string = pickle.dumps(a)
on the receiver side you unpickle the object:
a = pickle.loads(received_string)
# a is now your sent array
It has been a while since this question was asked, but I thought it's worth sharing the jsonsocket library. It makes it really easy to send strings, lists and dictionaries over sockets. It can handle big amounts of data efficiently. And you don't need to do any manual serialization/deserialization. Under the hood, it serializes the data as JSON strings on the client, and deserializes it on the server.
If you don't need UDP specifically, try zmqObjectExchanger (https://github.com/ZdenekM/zmq_object_exchanger). It wraps pickle and zmq to transfer python objects over TCP.

Categories