Python 高级网络操作 - Python Advanced Network Operations
生活随笔
收集整理的這篇文章主要介紹了
Python 高级网络操作 - Python Advanced Network Operations
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 Python 高級網絡操作 - Python Advanced Network Operations
2
3 Half Open Socket,
4 一個單向的 socket 被稱為 half open socket, 即數據只能在一個方向上傳輸.
5 Half Open Socket 是通過在 socket 對象上調用 shutdown() 方法得到.
6 shutdown 接收一個 numeric 類型的參數,
7 0 - 表示調用之后禁止讀
8 1 - 表示調用之后禁止寫
9 2 - 表示調用之后禁止讀和寫
10 一旦關閉了某一個方向(讀/寫), socket 就不能再在該方向上被重新打開了.
11 shutdown()是累計的, 也就是調用 shutdown(0) 再調用 shutdown(1) 跟
12 直接調用一個 shutdown(2) 效果是一樣的.
13
14 Half Open Socket 通常被應用在一下兒 3 種情形中,
15 1, 想要確保所有寫好的數據都已經被傳送出去.
16 調用 shutdown()的時候, 只有在緩存里面的數據都被成功發出去后方法才會有返回.
17 2, 用來 debug, 捕獲潛在的異常/錯誤.
18 Half Open Socket 是捕獲試圖寫一個不可寫的 socket, 或者讀一個不可讀
19 的 socket 的異常的好方法.
20 3, 在程序是用了 fork() 或 多線程的時候, 用來防止其他進程/線程的某些操作.
21
22 socket 超時 - socket timeout
23 settimeout(seconds)
24 對一個 socket 對象調用 settimeout(secs) 方法后, 如果經過在 sces 秒之內什么都
25 沒有發生(讀/寫), 則會產生一個 socket.timeout 異常, 鏈接機會斷開,
26 例子,
27 ... ...
28 sock, addr = S.accept()
29 sock.settimeout(9)
30 ... ...
31
32 結束標識,
33 通過 socket 傳輸不確定長度的字符串的會遇到一個問題 - 不知道什么時候數據發送結束.
34 通常,有兩種方法可以解決這個問題,
35 1, 通過指定字符串結束標識符(尾)
36 這個標識符通常是一個 NULL 字符(python - '\0') 或 newline 字符(python - '\n')
37 需要注意的問題是需要保證設定的結束符在所傳輸的內容中的'唯一'性.
38 2, 通過指定字符串長度指示符(首)
39 先發發送一個數字用來表示數據的長度, 接受方會根據這個數字長度的數據.
40 在網絡上發送整形數據的時候,通常有一下兒兩種選擇,
41 a, 發送 ASCII 碼(接收方收到后需要解碼)
42 b, 直接發送 二進制 數, 一般位長是 16 或 32 位.
43 為了解決不同平臺的二進制數據的編碼方法不同的問題, 一種標準的二進制數據
44 表示法 - 網絡字節順序( Network Byte Order )被采納. 在發送一個二進制數之前,
45 該二進制數被轉換成 Network Byte Order; 接收方收到后, 在使用該數據之前做
46 '反向轉換'.
47
48 廣播數據,
49 廣播數據不能用 TCP 實現, 他多數是用 UDP 來實現的.
50 當接受方收到一個廣播信息后, 系統內核會檢查目的地的端口號信息. 如果系統上有一個在 listen 監聽該端口
51 號的進程,則信息會被發送給該進程, 否者信息會被忽略掉.
52 例子,
53 發送方,
54 import socket
55 S = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
56 S.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 廣播 broadcast
57 S.sendto("Hi there!",('<broadcast>', 12345)) # host = '<broadcast>'
58
59 while 1:
60 try:
61 data, addr = S.recvfrom(1024)
62 print("%s is connecting" % clientsocket.getpeername())
63 except (KeyboardInterrupt,SystemExit) as e:
64 print(e)
65 raise
66 if not len(data):
67 break
68 print("Received message : %s from : %s",(data, addr))
69
70 接受方,
71 import socket
72
73 S = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
74 S.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 鏈接關閉后,端口立即可用
75 S.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 廣播 broadcast
76 S.bind(('', 12345))
77
78 while 1:
79 try:
80 mes, addr = S.recvfrom(8192)
81 print("Got message : %s from : %s" % (mes, addr))
82 S.sendto("ACK", addr) # 回復不是廣播
83 except (KeyboardInterrupt, SystemExit) as e:
84 print(e)
85 raise
86
87 通過 poll() 或 select() 實現事件通知,
88 通常, socket 上的 I/O 是阻塞的, 當一個操作(讀/寫)未結束,程序會阻塞.
89 在 nonblocking 模式中, 如果在沒有完全準備好的 socket 對象調用 send() 或 recv() 方法
90 會觸發 socket.error 異常. 在這種情況下, 就需要在調用 recv() 之前檢查一下兒, socket 上
91 是不是有可以接受的 data. select() 和 poll() 就是滿足檢查需求的兩個標準工具. 他們可以使
92 系統在某個 socket 上有事件發生的時候通知程序發生了什么, 從而在程序中進行有針對性的操作.
93 select() 接口是早起被普遍使用的, 但是在需要同時觀察多個 socket 的事件的時候, 會變得很慢.
94 Windows 系統不支持 poll(), 必須使用 select().
95
96 例子,
97 poll()
98 import socket, select
99 try:
100 S = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
101 except socket.error as e:
102 print("Error at creating socket : %s" % e)
103
104 try:
105 s.connect(("www.zzyzz.top", 80))
106 except socket.gaierror as e:
107 print("Address related error : %s" % e)
108 except socket.error as e:
109 print("Connection error : %s" % e)
110 P = select.poll()
111 P.register(S.fileno(), select.POLLIN | select.POLLERR | select.POLLHUP)
112 # POLLIN 普通或優先級帶數據可讀
113 # POLLERR 發生錯誤
114 # POLLHUP 對方描述符掛起
115 # POLLRDNORM 普通數據可讀
116 # POLLRDBAND 優先級帶數據可讀
117 # POLLPRI 高優先級數據可讀
118 # POLLOUT 普通數據可寫
119 # POLLWRNORM 普通數據可寫
120 # POLLWRBAND 優先級帶數據可寫
121 # POLLNVAL 描述字不是一個打開的文件
122
123 while 1:
124 res = P.poll(100) # poll 間隔 100 毫秒
125 if len(res):
126 if res[0][1] == select.POLLIN:
127 data = S.recv(1024)
128 if not len(data):
129 print("Connection closed")
130 break
131 print("Received data : %s" % data)
132 else:
133 print("Errors occurred")
134 break
135
136 select() 來解決 I/O 阻塞
137 select(rlist, wlist, elist[, timeout])
138 rlist - '讀' 的文件對象列表
139 wlist - '寫' 的文件對象列表
140 elist - '錯誤' 的文件對象列表
141 timeout - 可選參數, 接收浮點類型, 指明超時的時間(秒)
142
143 select() 方法的調用返回 3 個tuple, 每一個 tuple 都是一個對象列表, 順序對應參數順序.
144
145 import socket, select
146 try:
147 S = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
148 except socket.error as e:
149 print("Error at creating socket : %s" % e)
150
151 try:
152 s.connect(("www.zzyzz.top", 80))
153 except socket.gaierror as e:
154 print("Address related error : %s" % e)
155 except socket.error as e:
156 print("Connection error : %s" % e)
157
158 while 1:
159 infds, outfds, errfds = select.select([S],[],[S],0.05)
160 if len(infds):
161 data = S.recv(1024)
162 if not len(data):
163 print("Connection closed")
164 break
165 print("Received data : %s" % data)
166 if len(errfds):
167 print("Errors occurred")
168 break
?
轉載于:https://www.cnblogs.com/zzyzz/p/7994036.html
總結
以上是生活随笔為你收集整理的Python 高级网络操作 - Python Advanced Network Operations的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java基础基础总结----- Date
- 下一篇: SpringBoot学习笔记(8):事物