2

i am having trouble and a lot of questions about socket programming attached code below ( all parts have been taken from the and written together) i am trying to send mouse data to the client ,howver getting the error:

Traceback (most recent call last):
  File "srvr.py", line 29, in <module>
    serv.sendall(status)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
TypeError: must be string or buffer, not int

Questions: 1.how do we send data over sockets other then strings or specifically without the .send("...") statement .continously changing data?? 2.what things should be kept in mind when sending stream of data?? 3.code written here is a mess, would gladly appreciate help to teach some code sense into me

Thank YOu

Code: server side:

from socket import *      #import the socket library
##let's set up some constants
HOST = ''    #we are the host
PORT = 29876    #arbitrary port not currently in use
ADDR = (HOST,PORT)    #we need a tuple for the address
BUFSIZE = 4096    #reasonably sized buffer for data

## now we create a new socket object (serv)
## see the python docs for more information on the socket types/flags
serv = socket( AF_INET,SOCK_STREAM)    

##bind our socket to the address
serv.bind((ADDR))    #the double parens are to create a tuple with one element
serv.listen(5) 
print 'listening...'

conn,addr = serv.accept() #accept the connection
print '...connected!'
mouse = file('/dev/input/mouse0')  
while True:  
    status, dx, dy = tuple(ord(c) for c in mouse.read(3))  

    def to_signed(n):  
        return n - ((0x80 & n) << 1)  

    dx = to_signed(dx)  
    dy = to_signed(dy)  
    conn.send(status)
conn.close()

client:

##client.py
from socket import *

HOST = 'localhost'
PORT = 29876    #our port from before
ADDR = (HOST,PORT)
BUFSIZE = 4096

cli = socket( AF_INET,SOCK_STREAM)
cli.connect((ADDR))
data = cli.recv(BUFSIZE)
while data != '':
    print data

cli.close()
1
  • 1
    The basics of any communication is the agreement of a common protocol, so both sides can make sense of what is being communicated. When using sockets to perform network communication, it is very common to pack the data in a common format, so the other side can unpack and understand what was sent. In Python, this is done using the struct module. If you want to continuously send data from some device, the common approach is to first let the client request that. Then the server starts sending the data. Commented Jan 5, 2013 at 2:24

2 Answers 2

2

While transferring data over network, it is very usual to pack it according to the big-endian byte order. Even though you have only three separates bytes at a time, and thus byte ordering doesn't matter, I still prefer to pack and unpack simply because it is a common way to communicate. Also, a common thing to do, when receiving network data, is to check whether you actually received the amount you were expecting, otherwise you have to request for more data. For simplicity, consider the following function for that:

def recv(sock, size):
    data = ''
    to_receive = size
    while to_receive > 0:
        data += sock.recv(to_receive)
        to_receive = size - len(data)
    return data

Now, what is lacking in your code is a common protocol. The client is acting as a receiver of raw meaningless data. Instead, it should be acting as a receiver of triplets. Besides that, I suggest to let the client request how many triplets he wants. Taking this into consideration, that is how I would change your client code to:

import sys
import socket
import struct

serv_host = ''
serv_port = 29876

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serv_host, serv_port))

# Tell the server how many triplets I want.
amount = int(sys.argv[1])
s.sendall(struct.pack('!i', amount))
pack_size = struct.calcsize('!bbb')
while amount:
    status, dx, dy = struct.unpack('!bbb', recv(s, pack_size))
    print status, dx, dy
    amount -= 1

s.close()

Now the server also needs to respect this newly imposed protocol. Note that a negative value effectively makes the client receive infinite triplets, that is intentional. Here is the modified server:

import socket
import struct

def to_signed(n):
    return n - ((0x80 & n) << 1)

mouse = open('/dev/input/mouse0')

host = ''
port = 29876
backlog = 5

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(backlog)
print 'Listening'
while True:
    client, address = s.accept()

    # Obtain the number of triplets the client wants.
    amount = struct.unpack('!i', recv(client, 4))[0]
    while amount: # Send the triplets as they become available.
        status, dx, dy = map(ord, mouse.read(3))
        dx, dy = to_signed(dx), to_signed(dy)
        print status, dx, dy
        client.sendall(struct.pack('!bbb', status, dx, dy))
        amount -= 1

    client.close()
Sign up to request clarification or add additional context in comments.

1 Comment

@ mmpg thank you for the code it works great PS:sorry for late reply
0

You need to convert the type of the data that you are sending to a string or a buffer. The error message is quite clear. You need to do conn.send(str(status)) instead. You shouldn't need to "continuously" change data, you should only have to do it once, to a str object. To control what is in this str object if you are ever using your own class, you might define a __str__ method.

2 Comments

Note that (assuming status being set to 2), send(str(status)) will send something like \x32\x00, where the other side may be waiting for \x00\x02 or \x02\x00 (depending on your protocol's byte order agreement).
@TinyT That's true. In that case you should use pack in the struct module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.