Python Sockets - Using Coordinates getPos - python

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.

Related

Send and receive to/from a UDP socket python3.4

i have these lines of code for sending and receving from a UDP socket in python3.4, in which i want to send a file from a user to the other.
This is the server side code:
...
data = file.read(1024)
n = int(fileSize / 1024) + 1
for i in range(n):
if(self.sock.sendto(data.encode(), ('127.0.0.1',int(self.nextUserPort)))):
print ("Sending ...")
data = file.read(1024)
print ("File has been Sent Completely!!!")
self.sock.sendto("END#".encode(), ('127.0.0.1',int(self.nextUserPort)))
And this is the client side code:
....
d = self.sock.recvfrom(1024)
data = d[0].decode()
addr = d[1]
try:
while (data.strip().find("END#") != 0) :
file.write(data.decode())
time1 = time.time()
data, addr = self.sock.recvfrom(1024)
time2 = time.time()
print ("download speed is "+ str(1.0/(time2-time1))+" kbps")
print ("File Downloaded Completely!!!!!")
except socket.timeout :
file.close()
self.sock.close()
But when i run the code i get the below error for the line f(self.sock.sendto(data.encode(), ('127.0.0.1',int(self.nextUserPort)))):
AttributeError: 'bytes' object has no attribute 'encode'
And when i remove the encode i get another error that when i searched it i got that i must encode it in python3.4.
The exception is telling you what the problem is:
AttributeError: 'bytes' object has no attribute 'encode'
And as it happens you want to send bytes, so no need to convert anything in this line.
"END#".encode() can be directly written as b"END#".
Unrelated to your question: You might want use a TCP socket or give the transfer some logic to cope with reordered, lost and duplicated packages.

Python How to distinguish data in python socket module(when server receive.)

I don't know how to distinguish data which received in server.
I want to distinguish the data by setting MessageID(example name) when I send data or receive data.
Here's the example.:
server
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host=''
port=int(input(Please Enter the port:))
s.bind((host,port))
s.listen(1)
conn, addr = s.accept()
print('Someone connected.He :%s'%addr)
while True:
data=conn.recv(1024,MessageID) # I want to make this.
print(data)
client
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host=''
port=int(input(Please Enter the port:))
s.connect((host,port))
data='hello world'
data=data.encode('utf-8') # I encoded data because Python 3.3.3's socket module doesn't
work with string(str) when I send data.
s.send(data,MessageID) # This is what I want.I want to set messageID which can distinguish data.
How to make like this?
How other programmers distinguish data in python..?
I really want is : Don't receive if not messageID which server want.
You will need to put the MessageID into the data you're sending. It might be a good idea to use some known protocol for the data, so you know what to expect, but here's a naive example. You will need to implement proper error handling. Note that you will also have to implement a loop to read all of the data, as reading the socket with a single recv will eventually lead to a situation where you're receiving partial messages. I don't really know what your data is so I won't make a guess about it.
The client
....
message_id = 1
data = '{}:hello world!'.format(message_id)
data = data.encode('utf-8')
s.send(data)
The server
while True:
data = conn.recv(1024)
if not data:
# Always handle the case where the client
# connects but sends no data. This means the socket is closed
# by the other end.
break
message_id, message = data.split(":", 1)
print "Got message, id: {}, data: {}".format(message_id, message)
If you'd implement this using pickle or json you could simply use dictionaries:
# Client
data = {'message_id': 1, 'message': 'hello world'}
data = pickle.dumps(data) # Or json.dumps(data)
s.send(data)
# Server
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)

Python sockets + select

i use this function to run my Server via Sockets:
def run(self):
# The 'main' function
print 'Running ... '
Running = True
while Running:
InList,OutList,ExceptList = select.select(self.Connections,[],[])
for Connection in InList:
if Connection == self.Server:
# Server got a new connecting Client
User, Adress = self.Server.accept() # New User Connection
Data = {'User':User,'Adress':Adress}
self.Connections.append(Data) # Store the new User Connection
print 'User ', Data, ' connected'
else:
# Some other Socket got data for the Server
Data = Connection.recv(1024)
if not Data:
print 'No new Data!'
break
print Data
However when sending data i am getting this Error: TypeError: argument must be an int, or have a fileno() method, on line 23 which is the select() line.
Looking up the manual and those examples (http://code.activestate.com/recipes/531824-chat-server-client-using-selectselect/ and http://ilab.cs.byu.edu/python/select/echoserver.html) i see no difference and dont understand why i wouldn't work. self.Connections contains only the Server socket and when using print self.Connections it gives me:
[<socket._socketobject object at 0x020B6BC8>]
stating, that it's a list i am passing to select() which should be correct.
What am i doing wrong? Thanks!
The first time select.select runs, there's no problem, because self.Connections contains only a socket object, which is perfectly valid.
In the second trip through the while loop, however, self.Connections has picked up another element: the Data dictionary constructed in the if Connection == self.Server: block. That dictionary is not an integer, and it doesn't have a fileno method, so select.select complains when it sees it.

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.

Python StreamRequestHandler

So i've got a socket server running the StreamRequestHandler class. The problem lies in writing back to the socket. MY client does not seem to receive the data.
class MyTCPHandler(SocketServer.StreamRequestHandler)
def handle(self):
while 1:
self.data = self.rfile.readline()
...process data and pref result...
self.wfile.write(result)
break
this seems straight forward, what am i missing. Is there a way to flush the send buffer, as the amount of data i send is very little?
If I understand it correctly, you have problems with sending data from the server to the client. I had the same problem. Turns out, wfile and rfile are of type BytesIO and take only binary data.
So if your result is a normal string, you'll have to make it binary.
bstring = b"your string"
bstring = bytes("normal string", "utf8")
class MyTCPHandler(SocketServer.StreamRequestHandler)
def handle(self):
while 1:
self.data = self.rfile.readline()
if not self.data:
break
self.wfile.write(b"Got some data\n")

Categories