我正在尝试简单的脚本客户端套接字。我的代码如下:
import pickle
import socket
pole = ["mail","firewall","fria"]
c=False
while c==False:
try:
client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
client.connect ( ( 'localhost', 1234 ) )
print("established")
c=True
except:
print(".")
i = (len(pole)-1)
while i>=0:
client.send(pickle.dumps(pole[i]))
pole.remove(pole[i])
i-=1
client.close()
另一端是“永远”的服务器。但是服务器仅接收一个数据。为什么没有所有领域?客户端“ while”循环应运行3次,因此应发送所有循环([[mail],“ firewall”,“ fria”])。这是服务器输出:
然后客户端结束。为什么?客户端应在发送所有数据后结束。为什么一个发送连接关闭后,为什么?
感谢帮助
编辑---> server.py:
import pickle
import socket
updated_data = []
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 1234 ) )
server.listen ( 5 )
while 1:
channel, details = server.accept()
print ('Received connection:', details [ 0 ])
updated_data.append(pickle.loads(channel.recv(1024)))
print (updated_data)
channel.close()
我刚刚测试了您的代码,它揭示了您send()
从循环中获取的所有消息都被服务器作为单个消息接收,并且pickle
仅首先加载它们。基本上,收到的消息是
b'\x80\x03X\x04\x00\x00\x00friaq\x00.\x80\x03X\x08\x00\x00\x00firewallq\x00.\x80\x03X\x04\x00\x00\x00mailq\x00.'
如您所见,所有pole
元素都在此字符串中-这意味着客户端在连接关闭之前发送所有数据,并且服务器从客户端接收所有数据。
解决方案是对消息进行构架(以设置消息的边界)。这个问题相对广为人知(针对tcp消息边界和tcp消息框架的Google搜索结果)。
我发现这篇博客文章非常有帮助。它说:
消息成帧通常使用两种方法:长度前缀和定界符。
长度前缀为每条消息加上该消息的长度。长度前缀的格式(和长度)必须明确说明。通常选择“ 4字节有符号小尾数”(即C#中的“ int”)。要发送消息,发送方首先将消息转换为字节数组,然后发送字节数组的长度,然后发送字节数组本身。
由于存在部分接收的可能性,因此接收带有长度前缀的消息比较困难。首先,必须将消息的长度读入缓冲区,直到缓冲区已满(例如,如果使用“ 4字节有符号小尾数法”,则该缓冲区为4字节)。然后分配一个第二缓冲区,并将数据读入该缓冲区。当第二个缓冲区已满时,则到达一条消息,然后返回读取下一条消息的长度。
定界符更复杂才能正确处理。发送时,通常必须使用转义功能替换数据中的任何定界符。接收代码无法预测传入消息的大小,因此必须将所有接收到的数据附加到接收缓冲区的末尾,并根据需要增加缓冲区。找到分隔符后,接收方可以对接收缓冲区应用转义功能以获取消息。如果消息永远不会包含定界符,则可以跳过转义/取消转义功能。
在您的特殊情况下,我将使用Python list
(将作为“自动分隔的容器”)进行序列化,pickle
因此我将不得不稍稍更改您的代码。
客户
import pickle
import socket
pole = ["mail","firewall","fria"]
c = False
while not c:
try:
client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
client.connect ( ( 'localhost', 1234 ) )
print("established")
c = True
except:
print(".")
# - i = (len(pole)-1)
# - import time
# - while i>=0:
# - client.send(pickle.dumps(pole[i]))
# - pole.remove(pole[i])
# - i-=1
# +
client.send(pickle.dumps(pole))
client.close()
服务器
import pickle
import socket
updated_data = []
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 1234 ) )
server.listen ( 5 )
while 1:
channel, details = server.accept()
print ('Received connection:', details[0])
data = channel.recv(1024)
if data:
# Deserialize
data = pickle.loads(data)
# We're able to extend the list with another list:
# [1, 2, 3].extend([4, 5, 6]) is [1, 2, 3, 4, 5, 6]
updated_data.extend(data)
print(updated_data)
channel.close()
现在代码可以工作了,服务器可以打印了
Received connection: 127.0.0.1
['mail', 'firewall', 'fria']
并按updated_data
预期增长。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句