2

我遇到了麻烦,并且有很多关于下面的套接字编程附加代码的问题(所有部分都取自并一起编写)我正在尝试将鼠标数据发送到客户端,但出现错误:

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

问题: 1.我们如何通过字符串以外的套接字发送数据,或者特别是没有 .send("...") 语句。连续更改数据?2.发送数据流时要注意什么?3.这里写的代码一团糟,很高兴能帮助我教一些代码意识

谢谢你

代码:服务器端:

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.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()
4

2 回答 2

2

通过网络传输数据时,通常按照大端字节序进行打包。即使您一次只有三个单独的字节,因此字节顺序并不重要,我仍然更喜欢打包和解包,因为它是一种常用的通信方式。此外,在接收网络数据时,通常要做的事情是检查您是否确实收到了您期望的数量,否则您必须请求更多数据。为简单起见,请考虑以下功能:

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

现在,您的代码中缺少的是通用协议。客户端充当原始无意义数据的接收者。相反,它应该充当三胞胎的接收者。除此之外,我建议让客户要求他想要多少个三胞胎。考虑到这一点,这就是我将您的客户端代码更改为:

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()

现在服务器也需要遵守这个新强加的协议。请注意,负值有效地使客户端接收到无限的三元组,这是有意的。这是修改后的服务器:

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()
于 2013-01-05T03:07:11.060 回答
0

您需要将要发送的数据类型转换为 astring或 a buffer。错误信息非常清楚。你需要这样做conn.send(str(status))。您不需要“连续”更改数据,您应该只需要对一个str对象执行一次。str如果您曾经使用自己的类,要控制此对象中的内容,您可以定义一个__str__方法。

于 2013-01-05T02:18:47.477 回答