请教如何使用python socket 发送的socket发送二进制数据

2638人阅读
软件和库使用(48)
最近跳槽到西安一家机器人公司,我们的产品属于教育机器人的范畴,为了增强客户吸引力,引进了一个智能家居公司的产品API接口,让机器人来操作智能家居
该公司的智能家居API是自定义TCP包,即直接在TCP头后面写自定义数据结构:
客户端请求下载 家具数据库 的格式
命令字(4字节,小端)
服务器返回请求结果 的格式
命令字(4字节,小端)
payload长度(4字节,小端)
payload(N*1字节)
11262(尺寸很大)
sqlite数据库
默认python socket只能收发字符串,需要借助struct才能收发二进制数据
cmd_word = 0x4c
tx_buf = struct.pack('&I', cmd_word)
sock.sendall(tx_buf)
tx_buf据struct的文档说是其对输入编码生成的字符串,用type(tx_buf)显示确实是&type 'str'&,print tx_buf显示字母L
但len(tx_buf) == 4, print repr(tx_buf)显示
'L\x00\x00\x00'
也就是说len('L\x00\x00\x00') == 4
对于从C语言转过来的人来说,上面情况真是理解不能,但它就是发送成功了
fp = open('house.db', 'wb+')
recv_cnt = 0
while True:
rx_buf = sock.recv(4096)
len_buf = len(rx_buf)
if len_buf ==0:
if recv_cnt == 0:
cmd_word, data_len_total = struct.unpack(rx_buf[0:8])
buf = buffer(rx_buf, 8, len_buf - 8)
fp.write(buf)
buf = buffer(rx_buf)
fp.write(buf)
recv_cnt = recv_cnt +1
0、接收自定义帧头时用unpack,可以获得结构体各字段取值
1、接收自定义帧内容(字节流)时不用unpack,因为unpack返回的是tuple,而write不支持tuple类型
2、因为是二进制写入,所以必须将str转成buffer类型
3、二进制数据很大时,底层会拆分成多个以太网帧,如果你sendall后马上recv,则可能只收到1448字节,不要担心,这是因为你recv时内核协议栈只有一帧这么多数据,它全部返回给你了,满足socket编程的标准

参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:195322次
积分:3538
积分:3538
排名:第6510名
原创:142篇
转载:26篇
评论:48条
(1)(1)(1)(4)(3)(3)(2)(4)(5)(1)(3)(3)(2)(3)(3)(3)(3)(1)(4)(4)(1)(1)(1)(2)(1)(2)(1)(1)(1)(1)(2)(2)(5)(5)(17)(6)(2)(1)(2)(8)(3)(1)(2)(2)(8)(4)(6)(1)(2)(1)(1)(1)(1)(1)(1)(3)(1)(1)(1)(3)(2)(1)(4)(1)(1)(1)(1)(2)Python网络编程基础笔记-Socket超时-python-电脑编程网Python网络编程基础笔记-Socket超时作者:佚名 和相关&&
1.socket超时,端程序# -*- coding: cp936 -*-"""设置超时时间测试端程序时间设置分别大于和小于5,大于5时,使用异常来捕获socket.timeout"""import sockethost = ""port = 50000s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.bind((host,port))s.listen(5)while 1:&&&&clientsock,clientaddr = s.accept()&&&&try:&&&&&&&&# 将超时时间设置为5&&&&&&&&clientsock.settimeout(5)&&&&&&&&buf = clientsock.recv(8196)&&&&&&&&if len(buf) != 0:&&&&&&&&&&&&print buf&&&&except socket.timeout:&&&&&&&&print "time out"&&&&clientsock.shutdown(socket.SHUT_RD)&&&&clientsock.close()2.socket超时户端测试程序# -*- coding: cp936 -*-"""设置超时时间客户端第一次测试将sleep的参数设置为10,端显示为"timeout"第二次测试将sleep的参数设置为2,服务器端显示为"message comes from timeout client""""import sockethost = "localhost"port = 50000s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect((host,port))import time# 运行两次,分别使用不同的时间值,指定大小依据server端的设置,现在服务端为5# 测试时使用10和2,测试settimeout的作用time.sleep(10)s.send("message comes from timeout client" + "\r\n")s.shutdown(socket.SHUT_WR)s.close()
相关资料:|||||||Python网络编程基础笔记-Socket超时来源网络,如有侵权请告知,即处理!编程Tags:                &                    3437人阅读
特别标注:
有些网站转载我的文章不标明出处,并且转载不到位,没有把相应的链接一块转过去,比如说下载链接或相关文献的链接等,导致一些网友阅读和使用出现障碍和知识的不连续,所以在此特别标注:我的这篇文章发表在CSDN博客上,可以到CSDN博客来阅读。
今天琢磨了一下Python UDP Socket 16进制数据发送。
原以为UDP发送和接受的都是字符,怎么能够发送16进制?但细想,其实接收的都是“******”这样的东东。所有,要想发送16进制也是可以做到的。
要实现这个东东,就得用到字节byte,因为Python中没有字节(Byte)类型(可以把这里的字符串理解为字节流),所以得用到python的struct模块来进行字节流转换。
我的思路是这样子的:
1、首先假设有这样一个16进制字符串str: B1 C2 FF 82
2、利用python的字符数组符号分割字符串str,把字符串里面的16进制数据字符分割出来:“B1”, &C2&, &FF&,&82&;
3、通过函数int( s, 16)把16进制转换成整形数【函数里面s代表一个16进制字符串】;
4、利用python提供的struct模块里的struct.pack(fmt,v1, v2, ...)函数把整形转换成字节流【具体知识请看附录】;
5、利用socket.sendto函数发送字节流。
【例子:部分重点代码】
addr1 = (&192.168.1.100&, &8000&)
UDPSock = socket(AF_INET, SOCK_DGRAM)
str = &B1C2FF82& #获取字符测
str1 = && #初始化
str2 = && #初始化
while str:
str1 = str[0:2] #分割字符串,获取前两个字符
s = int( str1, 16) #字符串转换成16进制
str2 += struct.pack('B', s) #转换成字节流,“B“为格式符,代表一个unsigned char (具体请查阅struct)
str = str[2:] #分割字符串,去掉字符串前两个字符
if(UDPSock.sendto(str2, addr1)):pass #UDP发送数据
UDPSock.close()
如此便可以实现UDP客户端的16进制发送。
此附录内容来自于此(已经过本人整理):
python只定义了6种数据类型,字符串,整数,浮点数,列表,元组,字典。
但是C语言中有些字节型的变量,在python中该如何实现呢?这点颇为重要,特别是要在网络上进行数据传输的话。
python提供了一个struct模块来提供转换。下面就介绍这个模块中的几个方法。
&&& struct.pack():
&&& struct.pack用于将Python的值根据格式符,转换为字符串(因为Python中没有字节(Byte)类型,可以把这里的字符串理解为字节流,或字节数组)。
其函数原型为:struct.pack(fmt, v1, v2, ...),参数fmt是格式字符串,关于格式字符串的相关信息如下图所示,v1, v2, ...表示要转换的python值。
下面的例子将两个整数转换为字符串(字节流):
&&& import struct
&&& str=struct.pack('ii',a,b)&&& #转换成字节流,虽然还是字符串,但是可以在网络上传输
&&& print len(str)&&&&&&&&&&&&&& #ii 表示两个int
8&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #可以看到长度为8个字节,正好是两个int型数据的长度
&&& print str
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& #二进制是乱码
&&& print repr(str)
'\x14\x00\x00\x00\x90\x01\x00\x00'&& #其中十六进制的 0xx分别表示20和400
&& 由此我们就可以任意的进行组包了,比如下面一个打包的例子,只介绍其中的pack
format = &!HH%ds& % len(data)
buffer = struct.pack(format,opcode,blocknumber,data)
& 我们要对一个数据进行打包,加上一些个包头,我们根据下面的格式符信息,知道H是unsigned short是2个字节,而s是char型。所以这个buffer就是2个字节的opcode,2个字节的blocknumber,和len长的char。
struct.unpack():
&& 我们接着上面的例子运行:
&&& a1,a2=struct.unpack('ii',str)
&&& print 'a1',a1
&&& print 'a2=',a2
可以看到 “ii”以四个字节为分界,把8个字节的str分成了两个int型的整数。
&struct.calcsize():用来计算特定格式的输出的大小,是几个字节,比如:
&&& struct.calcsize('HH4s')
&&& struct.calcsize('ii')
&&& format='!HH%ds' % len('hello python')
&&& struct.calcsize(format)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:57806次
排名:千里之外
原创:21篇
评论:219条
(1)(1)(1)(1)(6)(3)(3)(1)(4)& & & &在工作中经常会用到socket传输数据,例如客户端给服务器发送数据(双方约定了数据格式),在交测之前,自己用python写个接受数据的server,解析下拼成的数据格式是否正确。用python写比C语言简单很多。
PS:实际上我是不会python的,工作中是C/C++开发,使用python纯属是为了偷懒^_^
& & & &举个具体的例子:通信双方约定的数据格式为& & & & &&
& & & &数据格式为二进制的,python需要用到struct模块处理二进制数据。struct模块中最重要的三个函数pack(), unpack(), calcsize()。因为struct相当于C语言中的结构体,unpack()返回的是一个元组。struct支持的格式如下表
& & & & 注1)q和Q只有在机器支持64位时有意义;
& & & & 注2)每个格式前可以有一个数字,表示个数;
& & & & 注3)s格式表示一定长度的字符串,4s表示长度为4的字符串,p表示的是pascal字符串;
& & & & 注4)P用来转换一个指针,其长度和机器字长有关;
默认情况下struct根据本地机器字节顺序转换,也可以用格式中的第一个字符来改变对齐方式。定义如下:
& & & & 注:无论数据包是python程序struct.pack()得到的,或者是C,C++,Java程序拼成的,只需保证client端和server端字节顺序保持一致即可。
& & & &以文章开头的例子来说明pack()和unpack()函数:
& & & & 注:测试环境中中文为utf-8编码(python的编码折腾了半天,也没太懂,这里不是重点)
& & & & 1)pack(format, v1, v2, ...)按照指定的格式(format),把数据封装成字符串,例如
& & & & & & & &&s=struct.pack("2i13si6s2i", 33, 13, "", 6, "冬季", 0, 0)
& & & & &2)unpack(format, string) & &按照给定的格式(fmt)解析字节流string,返回解析出来的tuple,例如& & & & & & & &&us=struct.unpack("2i13si6s2i", s)
& & & & & 输出结果:
& & & & & & & &&print us& & & & & & & (33, 13, '', 6, '\xe5\x86\xac\xe5\xad\xa3', 0, 0)
& & & & &&& & & & &注: 中文部分是二进制,从元组中取出来再打印
& & & & & & & && print us[4]& & & & & & & &冬季
& & & & & & & 注:对python下的中文编码感兴趣的同学可以研究下python环境编码(再次说明我真的不会python! &_&)
举个简单的例子:
#!/usr/bin/python
import socket
import struct
import time
if __name__ == "__main__":
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 51001)) #本机端口号51001
server.listen(1)
while (1):
conn,client = server.accept()
conn.settimeout(5000)
#设置超时时间
msg = conn.recv(4)
#total data length
if len(msg) &= 0:
#接收空数据包
data = struct.unpack("i", msg)
print "Recv Total length:%d"%(data[0])
process_len = 0
msg = conn.recv(data[0])
for i in range(0,4):
#循环四次,分别取 url title content author
para = msg[process_len:(process_len + 4)]
if len(para) & 4:
#如果某一字段为空,不处理
data = struct.unpack("i", para)
str_len = data[0]
print "%d"%(str_len)
para = msg[(process_len + 4):(process_len + 4 + str_len)]
if len(para) & str_len:
#如果实际收到的字符串长度小于数据头给的长度,不处理
data = struct.unpack("%ds"%(str_len), para)
print "%s"%(data[0])
process_len = process_len + 4 + str_len
conn.close()
阅读(...) 评论()}

我要回帖

更多关于 websocket 发送二进制 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信