python如何区分字符串和二进制消息 - TCP Socket发送

时间:2017-02-28 22:14:16

标签: python sockets tcp binary

我在user3132092的stackoverflow(link)中找到了一个TCP客户端发送" Hello world"通过TCP的字符串:

发送字符串

import socket

host = socket.gethostname()
port = 12345                   # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(b'Hello, world')

问题是s.sendall()接受字符串作为参数的方式与接受二进制文件的方式相同吗?是" Hello world"转换为二进制?

在这个例子中(链接)s.sendall(link)正在发送一个二进制文件,该二进制文件先前使用python结构转换为二进制文件。为什么结构对于" Hello World"?

不是必需的

发送二进制文件

import struct

values = (1, 'ab', 2.7)
packer = struct.Struct('I 2s f')
packed_data = packer.pack(*values)

print >>sys.stderr, 'sending "%s"' % binascii.hexlify(packed_data), values
sock.sendall(packed_data)

3 个答案:

答案 0 :(得分:1)

您正在使用Python 2,而b'...'语法实际上并不会产生单独的对象类型:

>>> import sys
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=13, releaselevel='final', serial=0)
>>> b'This is just a string'
'This is just a string'
>>> 'This is also just a string'
'This is also just a string'
>>> type(b'Just a string')
<type 'str'>
>>> type('Just a string')
<type 'str'>

{2}语法仅存在于Python 2中,以便更轻松地构建适用于Python 2和3的代码而无需更改。

b'...'模块还会生成struct个字符串对象:

str

因此,您始终发送>>> import struct >>> values = (1, 'ab', 2.7) >>> packer = struct.Struct('I 2s f') >>> packed_data = packer.pack(*values) >>> packed_data '\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@' >>> type(packed_data) <type 'str'> 字符串对象,此处不涉及任何魔法。在Python 2中,str对象实际上只是一系列字节。

答案 1 :(得分:0)

你必须指定你正在使用哪个python,Python 2和3中的- (BOOL)canBecomeFirstResponder { return YES; } - (NSArray *)keyCommands { return @[[UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:0 action:@selector(moveDownOneRow:) discoverabilityTitle:@"Select row down"], [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:0 action:@selector(moveUpOneRow:) discoverabilityTitle:@"Select row up"]]; } - (void)moveDownOneRow:(id)sender { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; if (indexPath == nil) { indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; } else { if ((indexPath.row + 1) < [self.tableView numberOfRowsInSection:0]) { indexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:0]; } } [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle]; } - (void)moveUpOneRow:(id)sender { NSIndexPath *indexPath = [self.tableViewindexPathForSelectedRow]; if (indexPath == nil) { indexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0]-1) inSection:0]; } else { if ((indexPath.row - 1) >= 0) { indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]; } } [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle]; } 是不同的,python2期待字符串,但python3正在期待字节。

请注意在python2中:

  

socket.sendall(string [,flags])   将数据发送到套接字。套接字必须连接到远程套接字。可选的flags参数与上面的recv()具有相同的含义。与send()不同,此方法继续从字符串发送数据,直到所有数据都已发送或发生错误。成功后不返回任何内容。出错时,会引发异常,并且无法确定成功发送了多少数据(如果有)。

Python3:

  

socket.sendall(bytes [,flags])   将数据发送到套接字。套接字必须连接到远程套接字。可选的flags参数与上面的recv()具有相同的含义。与send()不同,此方法继续从字节发送数据,直到所有数据都已发送或发生错误。成功后不返回任何内容。出错时,会引发异常,并且无法确定成功发送了多少数据(如果有)。

答案 2 :(得分:0)

如果您阅读了与struct sendall示例链接的页面,您将看到......

values = (1, 'ab', 2.7)
packer = struct.Struct('I 2s f')

......导致......

sending "0100000061620000cdcc2c40" (1, 'ab', 2.7)

所以它发送一个整数(1 / I),然后是两个字符的字符串('ab'/ 2s),最后是一个浮点值(2.7 / f)。这些是以二进制形式连续打包的,整数和浮点值使用相同的位发送,用于将它们存储在内存中 - 如果需要重新排列到便携式机器独立的“网络”字节序排序,这样另一方就能解压缩他们 - 而不是将它们转换为人类可读的文本。发送数据中间的6162是'ab'的ASCII编码。 61 hex是'a',62'b'。结构用于将所有这三个部分组合在一起,但如果您只是发送一串文本数据,则不需要它。