日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程 TCP

發布時間:2025/5/22 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程 TCP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、TCP協議

1. TCP協議的特點

1.TCP是面向連接的運輸層協議。這就意味著,在使用該協議之前,必須建立TCP連接。在傳輸數據完畢后,必須釋放已經建立的TCP連接。2.每一條TCP連接只能有兩個端點,每一條TCP連接只能是點對點的(一對一)。 3.TCP提供可靠交付的服務。通過TCP連接傳送的數據,無差錯、不丟失、不重復、并且按序到達。 4.TCP提供全雙工通信。TCP允許通信雙方的應用進程在任何時候都能發送數據。 TCP連接的兩端都設有發送緩存和接收緩存,用來臨時存放雙向通信的數據。 在發送時,應用程序在把數據傳送給TCP的緩存后,就可以做自己的事,而TCP在合適的時候把數據發出去。 在接收時,TCP把收到的數據放入緩存,上層的應用進程在合適的時候讀取緩存中的數據。 5.面向字節流。雖然應用程序和TCP的交互試一次一個數據塊(注意:大小是不等的), 但TCP把應用程序交下來的數據僅僅看成是一連串的無結構的字節流。TCP并不知道所傳送的字節流的含義。

2.三次握手、四次揮手

3.代碼實現

3.1 使用TCP協議實現簡單通信
# 客戶端: import socketclient = socket.socket() client.connect(('127.0.0.1', 8080)) client.send(b"this is client!") data = client.recv(1024) print(data) client.close() # 服務端: import socket server = socket.socket() # 實例化sever對象-->買手機 server.bind(('127.0.0.1', 8080)) # 綁定ip和端口-->手機卡 server.listen(5) # 監聽 -->打開手機 conn, addr = server.accept() # 等待建立連接 data = conn.recv(1024) # 接收數據 --> 打電話 print(data) conn.send(b"received data!!") conn.close() # 關閉連接-->掛電話 server.close() # 關閉服務器 -->關機
3.2 使用TCP協議實現通信循環
# 客戶端: import socketclient = socket.socket() client.connect(('127.0.0.1', 8080)) while True: msg = input(">>>") if msg == 'q': break client.send(msg.encode('utf-8')) data = client.recv(1024) print(data) client.close() # 服務端 import socket server = socket.socket() # 實例化sever對象-->買手機 server.bind(('127.0.0.1', 8080)) # 綁定ip和端口-->手機卡 server.listen(5) # 監聽 -->打開手機 conn, addr = server.accept() # 等待建立連接 while True: try: data = conn.recv(1024) # 接收數據 --> 打電話 print(data) conn.send(b"received data!!") except ConnectionResetError: break conn.close() # 關閉連接-->掛電話 server.close() # 關閉服務器 -->關機
3.3 使用TCP協議實現鏈接循環
# 客戶端 import socketclient = socket.socket() client.connect(('127.0.0.1', 8080)) while True: msg = input(">>>") if msg == 'q': break client.send(msg.encode('utf-8')) data = client.recv(1024) print(data) client.close() # 服務端 import socket server = socket.socket() # 實例化sever對象-->買手機 server.bind(('127.0.0.1', 8080)) # 綁定ip和端口-->手機卡 server.listen(5) # 監聽 -->打開手機 (半連接池) while True: conn, addr = server.accept() # 等待建立連接 while True: try: data = conn.recv(1024) # 接收數據 --> 打電話 print(data.decode('utf-8')) conn.send(b"received data!!") except ConnectionResetError: break conn.close() # 關閉連接-->掛電話 server.close() # 關閉服務器 -->關機
3.4 使用TCP協議實現粘包問題
# 客戶端 import socket import struct import jsonclient = socket.socket() client.connect(('127.0.0.1', 8090)) while True: msg = input(">>>").encode('utf-8') if len(msg) == 0: continue client.send(msg) header = client.recv(4) # 對頭進行解包,獲取真實數據的長度 head_len = struct.unpack('i', header)[0] head_dic = json.loads(client.recv(head_len).decode('utf-8')) print(head_dic) # 對需要接收的數據進行循環接收 total_size = head_dic['len'] recv_size = 0 res = b'' while recv_size < total_size: data = client.recv(1024) res += data recv_size += len(data) print(res.decode("gbk")) # 服務端 import socket import subprocess import struct import json server = socket.socket() # 實例化sever對象-->買手機 server.bind(('127.0.0.1', 8090)) # 綁定ip和端口-->手機卡 server.listen(5) # 監聽 -->打開手機 (半連接池) while True: conn, addr = server.accept() # 等待建立連接 while True: try: data = conn.recv(1024).decode('utf-8') # 接收數據 --> 打電話 if len(data) == 0: break # 針對mac和Linux,客戶端異常斷開反復收空的情況 # 生成一個能夠讀取輸出、錯誤流的對象 obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = obj.stdout.read() # 獲得輸出流 stderr = obj.stderr.read() # 獲取錯誤流 # 打印輸出流+輸入流的長度 print(len(stdout+stderr)) # 制作一個文件頭 header_dic = { 'filename': 'cls.avi', 'len': len(stderr+stdout) # 錯誤流 或者 輸出流 的長度 } # 序列化文件頭字典,得到文件頭的二進制文件 header_bytes = json.dumps(header_dic).encode('utf-8') # 制作報頭 header = struct.pack('i', len(header_bytes)) # 將要發送給客戶端的數據打包成固定4個字節 conn.send(header) conn.send(header_bytes) conn.send(stdout+stderr) except ConnectionResetError: break conn.close() # 關閉連接-->掛電話 server.close() # 關閉服務器 -->關機
3.5 解決粘包問題用到的 struct
1.說明struct模塊中最重要的三個函數是pack(), unpack(), calcsize()pack(fmt, v1, v2, ...) 按照給定的格式(fmt),把數據封裝成字符串(實際上是類似于c結構體的字節流)unpack(fmt, string) 按照給定的格式(fmt)解析字節流string,返回解析出來的tuplecalcsize(fmt) 計算給定的格式(fmt)占用多少字節的內存struct中支持的格式如下表: 網址 : https://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 2.代碼實現(例子) import struct data = 'datafa' # 服務端 res = struct.pack('i', len(data)) print(res) # b'\x06\x00\x00\x00' print(len(res)) # 4
3.6 解決粘包問題用到的 subprocess
1.說明 subprocess 模塊允許你生成新的進程,連接它們的輸入、輸出、錯誤管道,并且獲取它們的返回碼。class subprocess.Popen(args, bufsize=-1, executable=None,stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None) 2.代碼實現(例子): cmd = r'dir file_list' obj = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout = obj.stdout.read() # 來接住stdout流 print('stdout', stdout.decode('gbk')) # 打印進程列表 stderr = obj.stderr.read() print('stderr', stderr.decode('gbk')) # 當上面的命令出錯時,接收錯誤流 # stderr 'tasklist1' 不是內部或外部命令,也不是可運行的程序或批處理文件。 # stdout 和 stderr同時存在的時候,有一個接收到了數據另一個就不會停止等待

二、UDP協議

1. UDP協議的特點

1.UDP是無連接的,即發送數據之前不需要建立連接(發送數據結束時也沒有連接可釋放),因此減少了開銷和發送數據之前的時延。2.UDP使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持復雜的連接狀態表。3.UDP是面向報文的。發送方的UDP對應用程序交下來的報文,在添加首部后就向下交付IP層。UDP對應用層交下來的報文,既不合并,也不拆分,而是保留這些報文的邊界。 4.UDP沒有擁塞控制,因此網絡出現的擁塞不會使源主機的發送速率降低。 5.UDP支持一對一,一對多,多對一和多對多的交互通信。 6.UDP的首部開銷小,只有8個字節,比TCP的20個字節的首部要短。

2. 代碼實現

2.1 使用UDP協議實現簡單通信
# 客戶端 import socketclient = socket.socket(type=socket.SOCK_DGRAM) data = b'this is client' server_addr = ('127.0.0.1', 8080) client.sendto(data, server_addr) data1, addr1 = client.recvfrom(1024) print(addr1) print(data1) # ('127.0.0.1', 8080) # b'THIS IS CLIENT' # 服務端 import socket server = socket.socket(type=socket.SOCK_DGRAM) # udp協議 server.bind(('127.0.0.1', 8080)) while True: data, addr = server.recvfrom(1024) print(data) data = data.decode('utf-8') data = data.upper() server.sendto(data.encode('utf-8'), addr) # b'this is client'
2.2 使用UDP協議實現極簡版QQ
# 客戶端 import socketclient = socket.socket(type=socket.SOCK_DGRAM) server_addr = ('127.0.0.1', 8080)while True: data = input(">>>:").strip() client.sendto(data.encode('utf-8'), server_addr) msg, addr = client.recvfrom(1024) print(msg.decode('utf-8')) # 服務端 import socket server = socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) while True: data, addr = server.recvfrom(1024) print(addr) print(data.decode('utf-8')) re_msg = input(">>>:") server.sendto(re_msg.encode('utf-8'), addr)
2.3 socketServer模塊可以使TCP通信達到并發效果
# 客戶端 import socketclient = socket.socket() client.connect(('127.0.0.1', 8080))while True: msg = input(">>>:") client.send(msg.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8')) # 服務端 import socketserver server_addr = ('127.0.0.1', 8080) class MySock(socketserver.BaseRequestHandler): def handle(self): # 通信循環 while True: data = self.request.recv(1024) # 接收數據 print(data.decode('utf-8')) re_msg = input(">>>:") self.request.send(re_msg.encode('utf-8')) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(server_addr, MySock) server.serve_forever()

轉載于:https://www.cnblogs.com/wangtenghui/p/10940535.html

總結

以上是生活随笔為你收集整理的网络编程 TCP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。