zoukankan      html  css  js  c++  java
  • python socket 二进制

    问题

           在工作中经常会用到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, "www.baidu.com", 6, "冬季", 0, 0)

             2)unpack(format, string)    按照给定的格式(fmt)解析字节流string,返回解析出来的tuple,例如
                  >>us=struct.unpack("2i13si6s2i", s)

              输出结果:

                  >>print us
                  (33, 13, 'www.baidu.com', 6, 'xe5x86xacxe5xadxa3', 0, 0)

                       注: 中文部分是二进制,从元组中取出来再打印

                  >> print us[4]
                   冬季

                  注:对python下的中文编码感兴趣的同学可以研究下python环境编码(再次说明我真的不会python! >_<)

    举个简单的例子:

    #!/usr/bin/python
    import socket
    import struct
    import os
    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:             #接收空数据包 
                continue
            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:         #如果某一字段为空,不处理
                    continue
                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:   #如果实际收到的字符串长度小于数据头给的长度,不处理
                    continue
                data = struct.unpack("%ds"%(str_len), para)
                print "%s"%(data[0])
                process_len = process_len + 4 + str_len 
            conn.close()
  • 相关阅读:
    Mysql流程控制语句和存储过程
    第七章 MySQL基础
    第六章 操作数据
    第四章 数据库操作
    第三章 使用MySQL图形化工具
    第二章 初识MySQL
    第一章 数据库基础
    Live555源码学习02 ---- 框架
    Live555源码学习01 ---- 编译
    SRS4.0之RTMP转WebRTC02 ---- RTMP推流到SRS
  • 原文地址:https://www.cnblogs.com/thbCode/p/4551266.html
Copyright © 2011-2022 走看看