Python 学习笔记 - socket(基本原理和流程)
在學(xué)Python之前,先復(fù)習(xí)一下網(wǎng)絡(luò)的基本概念。
比如TCP/IP 4層模型,最上面的應(yīng)用軟件發(fā)送數(shù)據(jù)包,數(shù)據(jù)包在運輸層加上TCP或者UDP的報頭,然后在網(wǎng)絡(luò)層加上IP的報頭,然后在數(shù)據(jù)鏈路層根據(jù)ethernet協(xié)議分割成幀,每個幀TCP的最大數(shù)值為1500個字節(jié),因此一個3200字節(jié)的包可以被分割成3個幀,然后依次從物理層發(fā)通過高低電壓(對應(yīng)0和1的二進(jìn)制)發(fā)送出去。接收方通過同樣的方式逆向的組合幀,然后依次去掉每一層的報文,最后獲得數(shù)據(jù)。
對于程序開發(fā)人員而言,如果直接和每一層的協(xié)議打交道會非常麻煩,所幸有了socket這樣一個抽象的接口,可以通過socket來進(jìn)行網(wǎng)絡(luò)通信的編程。
Socket的基本流程如下所示
簡單的理解一下基本函數(shù):
socket()因為socket的本質(zhì)就是一個特殊的文件,這個相當(dāng)于普通文件的open操作。打開的時候 可以指定IP地址類型,TCP或者UDP等等;
bind()綁定端口和IP地址
listen()指定backlog的數(shù)目,即可以排隊連接的最大個數(shù)。
accept()可以監(jiān)聽指定的socket地址,阻塞直到有客戶端發(fā)送請求連接
connect()客戶端可以發(fā)送請求,連接到服務(wù)器
read()讀取數(shù)據(jù)
write()發(fā)送數(shù)據(jù)
close()雙方可以隨時終止連接
其他函數(shù)的具體解釋可以參考
http://www.cnblogs.com/wupeiqi/articles/5040823.html
為了更好的理解socket的連接和斷開,我們需要了解TCP的握手和斷開的流程。
TCP 3次握手連接
當(dāng)客戶端調(diào)用connect時,觸發(fā)了連接請求,向服務(wù)器發(fā)送了SYN J包,這時connect進(jìn)入阻塞狀態(tài);
服務(wù)器監(jiān)聽到連接請求,即收到SYN J包,調(diào)用accept函數(shù)接收請求向客戶端發(fā)送SYN K ,ACK J+1,這時accept進(jìn)入阻塞狀態(tài);
客戶端收到服務(wù)器的SYN K ,ACK J+1之后,這時connect返回,并對SYN K進(jìn)行確認(rèn);服務(wù)器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
TCP 4次分手?jǐn)嚅_連接
某個應(yīng)用進(jìn)程首先調(diào)用close主動關(guān)閉連接,這時TCP發(fā)送一個FIN M;
另一端接收到FIN M之后,執(zhí)行被動關(guān)閉,對這個FIN進(jìn)行確認(rèn)。它的接收也作為文件結(jié)束符傳遞給應(yīng)用進(jìn)程,因為FIN的接收意味著應(yīng)用進(jìn)程在相應(yīng)的連接上再也接收不到額外數(shù)據(jù);
一段時間之后,接收到文件結(jié)束符的應(yīng)用進(jìn)程調(diào)用close關(guān)閉它的socket。這導(dǎo)致它的TCP也發(fā)送一個FIN N;
接收到這個FIN的源發(fā)送端TCP對它進(jìn)行確認(rèn)
下面看個簡單的例子:
server.py
import?socket ip_port=('127.0.0.1',5555) s=socket.socket() s.bind(ip_port) s.listen(5) conn,addr=s.accept() while?True:try:recv_data=conn.recv(1024)if?str(recv_data,encoding='utf-8')=='exit':breakprint(str(recv_data,encoding='utf8'))send_data=recv_data.upper()conn.send(send_data)#如果客戶端斷開連接,服務(wù)器會拋出異常,自動停止except?Exception?as?ex:break conn.close()client.py
import?socket ip_port=('127.0.0.1',5555) s=socket.socket() s.connect(ip_port) while?True:data=input('>>').strip()if?len(data)==0:continue #如果直接輸入空格或者回車,直接會卡住,因為服務(wù)器方面recv不會接受空值,會導(dǎo)致阻塞s.send(bytes(data,encoding='utf8'))if?data=='exit':breakrecv_data=s.recv(1024)print(str(recv_data,encoding='utf8')) s.close()結(jié)果如下:
客戶端效果
"C:\Program?Files\Python3\python.exe"?C:/Users/yli/pycharmprojects/Exercise/week9/client1.py >>aaa AAA >>bbb BBB >>Exit EXIT >>exit轉(zhuǎn)載于:https://blog.51cto.com/beanxyz/1858942
總結(jié)
以上是生活随笔為你收集整理的Python 学习笔记 - socket(基本原理和流程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle database link
- 下一篇: rhel6下组建两台主机的HA集群