我正在尝试使用socket
库发送消息。由于消息是可变大小的,我决定在字符串的开头附加消息的大小,然后发送它。例如,如果消息是
Hello World!
这是13个字符长(我算过EOL),我会发送类似
的内容sizeof13charsinbytes|Hello World!
通过socket.send()
,然后我会用str.split()
由于socket.recv()
需要以字节为单位的邮件大小,如何查找邮件的大小?我尝试了sys.getsizeof()
,但它为单字符字符串提供了任意值。尺寸合适吗?
答案 0 :(得分:4)
没有必要重新发明轮子。通过使用multiprocessing.connection
模块将字符串作为python字符串对象发送,可以轻松地发送可变长度字符串。此方法将允许发送大多数python对象,而不仅仅是字符串。
import multiprocessing
import multiprocessing.connection as connection
def producer(data, address, authkey):
with connection.Listener(address, authkey=authkey) as listener:
with listener.accept() as conn:
print('connection accepted from', listener.last_accepted)
for item in data:
print("producer sending:", repr(item))
conn.send(item)
def consumer(address, authkey):
with connection.Client(address, authkey=authkey) as conn:
try:
while True:
item = conn.recv()
print("consumer received:", repr(item))
except EOFError:
pass
listen_address = "localhost", 50000
remote_address = "localhost", 50000
authkey = b'secret password'
if __name__ == "__main__":
data = ["1", "23", "456"]
p = multiprocessing.Process(target=producer, args=(data, listen_address, authkey))
p.start()
consumer(remote_address, authkey)
p.join()
print("done")
产生类似的东西:
producer sending: '1'
producer sending: '23'
consumer received: '1'
producer sending: '456'
consumer received: '23'
consumer received: '456'
done
答案 1 :(得分:1)
它常见于这种情况下读取标头以获取大小然后读取有效负载。如果标题是固定大小(可能是一个二进制整数,也许是带有填充的固定大小ascii字符串),它会更容易一些,但你也可以逐字逐句阅读,直到你找到一个分隔符,如' |' 。我在下面有几个样本。
import struct
def _get_block(s, count):
if count <= 0:
return ''
buf = ''
while len(buf) < count:
buf2 = s.recv(count - len(buf))
if not buf2:
# error or just end of connection?
if buf:
raise RuntimeError("underflow")
else:
return ''
buf += buf2
return buf
def _send_block(s, data):
while data:
data = data[s.send(data):]
if False:
def get_msg(s):
count = struct.unpack('>i', _get_block(s, 4))[0]
return _get_block(s, count)
def send_msg(s, data):
header = struct.pack('>i', len(data))
_send_block(s, header)
_send_block(s, data)
if True:
def _get_count(s):
buf = ''
while True:
c = s.recv(1)
if not c:
# error or just end of connection/
if buf:
raise RuntimeError("underflow")
else:
return -1
if c == '|':
return int(buf)
else:
buf += c
def get_msg(s):
return _get_block(s, _get_count(s))
def send_msg(s, data):
_send_block(s, str(len(data)) + '|')
_send_block(s, data)
import threading
import socket
import time
def client(port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('0.0.0.0', port))
print get_msg(s)
print get_msg(s)
s.shutdown(socket.SHUT_RDWR)
s.close()
def server(port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', port))
s.listen(1)
c, addr = s.accept()
send_msg(c, 'hello')
send_msg(c, 'there')
c.close()
s.close()
if __name__ == '__main__':
c = threading.Thread(target=server, args=(8999,))
c.start()
time.sleep(1)
client(8999)
c.join()
print 'done'
答案 2 :(得分:0)
序列化数据后,您只需使用len(your_serialized data)
即可获取其长度。
下面是发送和接收功能的示例,您可以在客户端和服务器端使用它来发送和接收可变长度数据。
def send_data(conn, data):
serialized_data = pickle.dumps(data)
conn.sendall(struct.pack('>I', len(serialized_data)))
conn.sendall(serialized_data)
def receive_data(conn):
data_size = struct.unpack('>I', conn.recv(4))[0]
received_payload = b""
reamining_payload_size = data_size
while reamining_payload_size != 0:
received_payload += conn.recv(reamining_payload_size)
reamining_payload_size = data_size - len(received_payload)
data = pickle.loads(received_payload)
return data
您可以在https://github.com/vijendra1125/Python-Socket-Programming.git上找到示例程序