問題python
在工做中常常會用到socket傳輸數據,例如客戶端給服務器發送數據(雙方約定了數據格式),在交測以前,本身用python寫個接受數據的server,解析下拼成的數據格式是否正確。用python寫比C語言簡單不少。服務器
PS:實際上我是不會python的,工做中是C/C++開發,使用python純屬是爲了偷懶^_^socket
舉個具體的例子:通訊雙方約定的數據格式爲
函數
數據格式爲二進制的,python須要用到struct模塊處理二進制數據。struct模塊中最重要的三個函數pack(), unpack(), calcsize()。由於struct至關於C語言中的結構體,unpack()返回的是一個元組。struct支持的格式以下表測試
注1)q和Q只有在機器支持64位時有意義;編碼
注2)每一個格式前能夠有一個數字,表示個數;url
注3)s格式表示必定長度的字符串,4s表示長度爲4的字符串,p表示的是pascal字符串;spa
注4)P用來轉換一個指針,其長度和機器字長有關;指針
默認狀況下struct根據本地機器字節順序轉換,也能夠用格式中的第一個字符來改變對齊方式。定義以下:code
注:不管數據包是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, '\xe5\x86\xac\xe5\xad\xa3', 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()