python中關於shutdown 和closesocket的徹底理解!


關於shutdown 和closesocket的徹底理解!

shutdown 和closesocket

    來,咱們徹底的來討論一下這個shutdown 和closesocket 從函數調用上來分析(msdn):一旦完成了套接字的連接,應當將套接字關閉,並且釋放其套接字句柄所占用的所有資源。真正釋放一個已經打開的套接字句柄的資源直接調用closesocket即可,但要明白closesocket的調用可能會帶來負面影響,具體的影響和如何調用有關,最明顯的影響是數據丟失,因此一般都要在closesocket之前調用shutdown來關閉套接字。
   shutdown:為了保證通信雙方都能夠收到應用程序發出的所有數據,一個合格的應用程序的做法是通知接受雙發都不在發送數據!這就是所謂的“正常關閉”套接字的方法,而這個方法就是由shutdown函數,傳遞給它的參數有SD_RECEIVE,SD_SEND,SD_BOTH三種,如果是SD_RECEIVE就表示不允許再對此套接字調用接受函數。這對於協議層沒有影響,另外對於tcp套接字來說,無論數據是在等候接受還是即將抵達,都要重置連接(注意對於udp協議來說,仍然接受並排列傳入的數據,因此udp套接字而言shutdown毫無意義)。如果選擇SE_SEND,則表示不允許再調用發送函數。對於tcp套接字來說,這意味着會在所有數據發送出並得到接受端確認后產生一個FIN包。如果指定SD_BOTH,答案不言而喻。
   closesocket:對此函數的調用會釋放套接字的描述,這個道理眾所周知(凡是經常翻閱msdn的程序員),因此,調用此函數后,再是用此套接字就會發生調用失敗,通常返回的錯誤是WSAENOTSOCK。此時與被closesocket的套接字描述符相關聯的資源都會被釋放,包括丟棄傳輸隊列中的數據!!!!對於當前進程中的線程來講,所有被關起的操作,或者是被掛起的重疊操作以及與其關聯的任何事件,完成例程或完成端口的執行都將調用失敗!另外SO_LINGER標志還影響着closesocket的行為,但對於傳統的socket程序,這里不加解釋
因此可以可以看出shutdown對切斷連接有着合理的完整性。
    下面從tcp協議上來分析shutdown和closesocket的行為(behavior):closesocket或shutdown(使用SD_SEND當作參數時),會向通信對方發出一個fin包,而此時套接字的狀態會由ESTABLISHED變成FIN_WAIT_1,然后對方發送一個ACK包作為回應,套接字又變成FIN_WAIT_2,如果對方也關閉了連接則對方會發出FIN,我方會回應一個ACK並將套接字置為TIME_WAIT。因此可以看出closesocket,shutdown所進行的TCP行為是一樣的,所不同的是函數部分,shutdown會確保windows建立的數據傳輸隊列中的數據不被丟失,而closesocket會冒然的拋棄所有的數據,因此如果你願意closesocket完全可以取代shutdown,然而在數據交互十分復雜的網絡協議程序中,最好還是shutdown穩妥一些!

python中socket.shutdown的用法

直接看代碼

'''
使用使用shutdown來關閉socket的功能
SHUT_RDWR:關閉讀寫,即不可以使用send/write/recv/read
SHUT_RD:關閉讀,即不可以使用recv/read
SHUT_WR:關閉寫,即不可以使用send/write
'''
import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("localhost",50000))
s.sendall("this is shutdown test" + "\r\n")
s.send("this is shutdown test")
s.shutdown(socket.SHUT_RDWR)
print(socket.SHUT_RDWR)
print(socket.SHUT_RD)
print(socket.SHUT_WR)
s.close()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM