UDP套接字和粘包


1.UDP套接字

  udp服務端:

1 ss = socket()           #創建一個服務器的套接字
2 ss.bind()                 #綁定服務器套接字
3 inf_loop:                 #服務器無限循環
4cs = ss.recvfrom()/ss.sendto() # 對話(接收與發送)
5 ss.close()               # 關閉服務器套接字

  udp客戶端:

1 cs = socket()           # 創建客戶套接字
2 comm_loop:             # 通訊循環
3 cs.sendto()/cs.recvfrom()   # 對話(發送/接收)
4 cs.close()                # 關閉客戶套接字

2.recv與recvfrom的區別:

  part1:

    發消息都是將數據發送到己端發送緩沖中,手消息都是從己端的緩沖區中收

    tcp:send發消息,recv收消息

    udp:sendto發消息,recvfrom收消息

  part2:

    tcp是基於數據流的,而udp是基於數據報的

    send(bytes_data):發送數據流,數據流bytes_data若為空,自己這段的緩沖區也為空,操作系統不會控制tcp協議發空包

    sendinto(bytes_data,ip_port):發送數據報,bytes_data為空,還有ip_port,所有即便是發送空的butes_data,數據報其實也不是空的,自己這端的緩沖區收到內容,操作系統就會控制udp協議發包.

  part3:

    1.tcp協議:

      (1)如果收消息緩沖區里的數據為空,那么recv就會阻塞(阻塞很簡單,就是一直在等着接收)

      (2)只不過tcp協議的客戶端send一個空數據就是真的空數據,客戶端即使有無窮個send空,也跟沒有一個樣.

      (3)tcp基於鏈接通信

        *基於鏈接,則需要listen(backlog),指定半連接池的大小

        *基於鏈接,必須先運行的服務端,然后客戶端發起鏈接請求

        *對於Mac空系統:如果一段斷開了鏈接,那另外一端的鏈接也跟着完蛋recv將不會阻塞,收到的是空(解決方法是:服務端在收消息后加上if判斷,空消息就break掉通信循環)

        *對於Windows/Linux系統:如果一端斷開了鏈接,那另外一端的鏈接也跟着完蛋recv將不會阻塞,收到的是空(解決方法:服務端通信循環內加異常處理,捕捉到異常后就break掉通訊循環)

    2.udp協議

      (1)如果收消息緩沖區里的數據為"空",recvfrom也會阻塞

      (2)支部會udp協議的客戶端sendinto一個空數據並不是真的空數據(包含:空數據+地址信息,得到的報仍然不會為空),所以客戶端只要有一個sendinto(不管是否發送空數據,都不會真的空數據),服務端就可以recvfrom到數據.

      (3)udp無鏈接

        *無鏈接,因而無需listen(backlog),更加沒有什么連接池之說了

        *無鏈接,udp的sendinto不用管是否有一個正在運行的服務端,可以己端一個勁的發消息,只不過數據丟失

        *recvfrom收的數據小於sendinto發送的數據時,在Mac和Linux系統上數據直接丟失,在Windows系統上發送的比接受的大直接報錯

        *只有sendinto發送數據沒有recvfrom收數據,數據丟失

  PS:

    1.你單獨運行上面的udp的客戶端,你發現並不會報錯,相反tcp卻會報錯,因為udp協議只負責把包發出去,對方收不收,我根本管不着,而tcp是基於鏈接的,必須有一個服務端先運行着,客戶端去跟服務端建立連接然后依托於連接才能傳遞消息,任何一方試圖把連接摧毀都會導致對方程序崩潰

    2.上面的udp程序,你注釋任何一條客戶端的sendinto,服務端都會卡住,為什么?因為服務端有幾個recvfrom就要對應幾個sendinto,哪怕是sendinto(b'')那也要有.

3.粘包現象:

  只有TCP有粘包現象,UDP永遠不會粘包!

  所謂的粘包問題主要還是因為接收對方不知道消息之間的界限,不知道一次性提取多少字節的數據造成的.

  以下情況會發生粘包:

  1.發送端需要等緩沖區滿才發送出去,造成粘包(發送數據時間間隔很短,數據量很小,會合到一起,產生粘包)

  2.接收方不及時接收緩沖區的包,造成多個包接收(客戶端發送一端數據,服務端只收了一小部分,服務端下次再收的時候還是從緩沖區拿上次遺留的數據,產生粘包)

4.解決粘包方法:

  struct模塊

  該模塊可以把一個類型,如數字,轉成固定長度的bytes

  >>>Struct.pack('i',111111111111)

  struct.error:'i' format requires -2147483648 <= number <=2147483647 #這個是范圍

 


免責聲明!

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



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