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

ネットワークを介してデータを転送する場合、ビッグエンディアンのバイト順序に従ってデータをパックするのが非常に一般的です。一度に3つの個別のバイトしかないため、バイトの順序は重要ではありませんが、通信の一般的な方法であるという理由だけで、パックとアンパックを選択します。また、ネットワークデータを受信するときによく行うことは、期待した量を実際に受信したかどうかを確認することです。そうでない場合は、追加のデータを要求する必要があります。簡単にするために、そのための次の関数を検討してください。

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

string送信するデータのタイプをまたはに変換する必要がありますbuffer。エラーメッセージは非常に明確です。conn.send(str(status))代わりに行う必要があります。データを「継続的に」変更する必要はありませんstr。オブジェクトに対して一度だけ変更する必要があります。str独自のクラスを使用している場合にこのオブジェクトの内容を制御するには、__str__メソッドを定義します。

于 2013-01-05T02:18:47.477 に答える