1. 程式人生 > 其它 >socket網路程式設計學習之tcp與udp

socket網路程式設計學習之tcp與udp

技術標籤:socketpython

1.(TCP)面向連線的套接字

不管你採用的是哪種地址家族,都有兩種不同風格的套接字連線。第一種是面向連線的
這意味著在進行通訊之前必須先建立一個連線,例如,使用電話系統給一個朋友打電話。這
種類型的通訊也稱為虛擬電路或流套接字。48 第 1 部分 通用應用主題
面向連線的通訊提供序列化的、可靠的和不重複的資料交付,而沒有記錄邊界。這基本
上意味著每條訊息可以拆分成多個片段,並且每一條訊息片段都確保能夠到達目的地,然後
將它們按順序組合在一起,最後將完整訊息傳遞給正在等待的應用程式。
實現這種連線型別的主要協議是傳輸控制協議(更為人熟知的是它的縮寫 TCP)。為 了

建立 TCP 套接字,必須使用 SOCK_STREAM 作為套接字型別。TCP 套接字的名字
SOCK_STREAM 基於流套接字的其中一種表示。因為這些套接字(AF_INET)的網路版本
使用因特網協議(IP)來搜尋網路中的主機,所以整個系統通常結合這兩種協議(TCP 和 IP)
來進行(當然,也可以使用 TCP 和本地[非網路的 AF_LOCAL/AF_UNIX]套接字,但是很明
顯此時並沒有使用 IP)。

2.(UDP)無連線的套接字

與虛擬電路形成鮮明對比的是資料報型別的套接字,它是一種無連線的套接字。這意味
著,在通訊開始之前並不需要建立連線。此時,在資料傳輸過程中並無法保證它的順序性、

可靠性或重複性。然而,資料報確實儲存了記錄邊界,這就意味著訊息是以整體傳送的,而
並非首先分成多個片段,例如,使用面向連線的協議。
使用資料報的訊息傳輸可以比作郵政服務。信件和包裹或許並不能以傳送順序到達。
事實上,它們可能不會到達。為了將其新增到併發通訊中,在網路中甚至有可能存在重複
的訊息。
既然有這麼多副作用,為什麼還使用資料報呢(使用流套接字肯定有一些優勢)?由於面
向連線的套接字所提供的保證,因此它們的設定以及對虛擬電路連線的維護需要大量的開銷。
然而,資料報不需要這些開銷,即它的成本更加“低廉”。因此,它們通常能提供更好的效能,
並且可能適合一些型別的應用程式。
實現這種連線型別的主要協議是使用者資料報協議(更為人熟知的是其縮寫 UDP)。為 了
建立 UDP 套接字,必須使用 SOCK_DGRAM 作為套接字型別。你可能知道,UDP 套接字的
SOCK_DGRAM 名字來自於單詞“datagram”(資料報)。因為這些套接字也使用因特網協議
來尋找網路中的主機,所以這個系統也有一個更加普通的名字,即這兩種協議(UDP 和 IP)
的組合名字,或 UDP/IP。

TCP服務端客戶端例項

from socket import *
IP = '0.0.0.0'
PORT = 1314
BUFLEN = 512
ssk = socket(AF_INET, SOCK_STREAM)
ssk.bind((IP,PORT))
ssk.listen(5)
print("服務端啟動成功,等待客戶端連線。。。")
tsk, addr = ssk.accept()
print("接受客戶端連線:",addr)

while True:
    #接受客戶端返回的位元組碼
    recved = tsk.recv(BUFLEN)
    if not recved:
        break
    message = recved.decode()#解碼成str
    print (f'收到對方資訊:{message}')
    # print('收到對方資訊:{message}')
    tsk.send(f"服務端收到了資訊{message}".encode())#編碼字串
    
tsk.close()
ssk.close()

from socket import *
IP = '127.0.0.1'
SERVER_PORT = 1314
BUFLEN = 512
tsk = socket(AF_INET, SOCK_STREAM)
tsk.connect((IP, SERVER_PORT))
while True:
    toSend = input('>>> ')
    if toSend == 'byebye':
            break
    tsk.send(toSend.encode())
    recved = tsk.recv(BUFLEN)
    if not recved:
        break
    print(recved.decode())
tsk.close()

2.UDP服務端和客戶端

from socket import * #匯入socket
from time import ctime
print("---------------------------服務端udp------------------------------------")
#設定埠,地址
PORT = 520
IP = '0.0.0.0'
MAX = 1024
#建立socket物件
usk = socket(AF_INET,SOCK_DGRAM)
#繫結埠地址
usk.bind((IP,PORT))
print("服務端啟動成功")

#資訊傳輸
while True:
    #接收資訊
    data,addr = usk.recvfrom(MAX)
    print("連線成功,等待對方傳送資訊")
    usk.sendto(('[%s] %s' %(ctime(),data)).encode(),addr)
usk.close()
from socket import * #匯入socket
print("---------------------------客戶端udp------------------------------------")
#埠地址
PORT = 520
IP= '127.0.0.1'
MAX = 1024
#建立
psk = socket(AF_INET,SOCK_DGRAM)
# #連線
# psk.connect((IP,PORT))
while True:
    data = input('>')
    if not data:
        break
    psk.sendto(data.encode(),(IP,PORT))
    data,(IP,PORT) = psk.recvfrom(MAX)
    if not data:
        break
        print(data)
psk.close()