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()
  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 洁净数
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数
    20. Valid Parentheses
    290. Word Pattern
    205. Isomorphic Strings
    71. Simplify Path
  • 原文地址:https://www.cnblogs.com/thbCode/p/4551266.html
Copyright © 2011-2022 走看看