【python高級】342-TCP服務器開發流程

CS模式:客戶端-服務端模式

TCP客戶端開發流程介紹(五步)(C端)
1.創建客戶端套接字對象
2.和服務端套接字建立連接
3.發送數據
4.接收數據
5.關閉客戶端套接字
TCP服務端開發流程(七步)(S端)
1.創建服務端端套接字對象
2.綁定端口號
3.設置監聽
4.等待接受客戶端的連接請求
5.接收數據
6.發送數據
7.關閉套接字

TCP客戶端程序開發

import socket# 第一步:創建客戶端套接字對象
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socket.AF_INET表示IPV4,socket.SOCK_STREAM表示TCP協議# 第二步:創建連接
tcp_client_socket.connect(("127.0.0.1", 8000))  # 參數是個元組# 第三步:發送數據到服務器端
tcp_client_socket.send("hello".encode("utf-8"))  # 這里將字符串編碼成二進制數據# 第四步:接收服務器端返回的數據
recv_data = tcp_client_socket.recv(1024).decode("utf-8")  # 1024表示本次接收的最大字節數,decode解碼
print(f"接收到的數據為:{recv_data}")  # 將二進制數據解碼成字符串# 第五步:關閉套接字對象
tcp_client_socket.close()

tip:發送和接受的都要是二進制數據,所以要用encode和decode方法將字符串轉換成二進制數據

  • encode():將字符串轉換成二進制數據
  • decode():將二進制數據轉換成字符串

關于socket.AF_INET、socket.SOCK_STREAM常量的介紹:

  • socket.AF_INET(IPv4)
    • 這是 Python 中socket模塊里的一個常量,AF_INET代表 Address Family(地址族)為INET,用于指定網絡通信使用的地址族是 IPv4 地址族。
    • 當創建一個套接字(socket)時,通過指定AF_INET,告訴操作系統這個套接字將用于基于 IPv4 協議的網絡通信。
  • socket.SOCK_STREAM(TCP)
    • 這是socket模塊中的另一個常量,用于指定套接字的類型為流套接字。
      • 當和AF_INET一起使用創建套接字時(如前面代碼示例中的socket.socket(socket.AF_INET, socket.SOCK_STREAM)),它表示創建的是一個基于 TCP(Transmission Control Protocol)協議的流套接字。TCP 是一種面向連接的、可靠的傳輸協議,SOCK_STREAM類型的套接字利用 TCP 協議提供的特性,如三次握手建立連接、數據的可靠傳輸(通過確認、重傳等機制)、流量控制和擁塞控制等。
      • 這種類型的套接字適用于需要保證數據準確無誤地傳輸的應用場景,比如 HTTP(超文本傳輸協議)用于網頁瀏覽,SMTP(簡單郵件傳輸協議)用于發送電子郵件等。它提供了一個字節流的接口,應用程序可以像讀寫文件一樣通過這個套接字進行數據的發送和接收,而不必擔心數據的丟失或損壞,因為 TCP 協議在底層會處理這些問題。

TCP服務端程序開發(重點)

開發的七步:
1.創建服務端套接字對象
2.綁定端口號
3.設置監聽
4.等待接受客戶端的連接請求:類似于input() → accept()阻塞
5.接收數據
6.發送數據
7.關閉套接字

服務器如何判斷是哪個客戶端連接:
通過accept()方法返回的套接字對象來區分不同的客戶端

import socket# 1.創建服務端套接字對象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # socket.AF_INET表示IPV4,socket.SOCK_STREAM表示TCP協議# 2.綁定端口號
tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本機,可以不寫ip地址# 3.設置監聽
tcp_server_socket.listen(128)  # 128表示最大連接數# 4.等待接受客戶端的連接請求
new_socket, ip_port = tcp_server_socket.accept()  # 阻塞狀態,等待客戶端連接
# tcp_server_socket對象主要用于接收客戶端連接:綁定端口、設置監聽、接收連接
# new_socket對象主要用于接收和發送數據
print(f"新連接的客戶端地址為:{ip_port}")
print(f"新連接的客戶端socket對象為:{new_socket}")# ================================================
# 5.接收數據
recv_data = new_socket.recv(1024).decode("utf-8")  # 1024表示本次接收的最大字節數,decode解碼	
print(f"接收到的數據為:{recv_data}")# 6.發送數據
new_socket.send("信息已收到".encode("utf-8"))  # 將字符串編碼成二進制數據# 7.關閉新套接字對象(關閉后不能收發消息)和服務端套接字對象(不能接收新連接)
new_socket.close()
tcp_server_socket.close()

當客戶端發送信息后,接收到的data是一個元組,下面是個栗子,元組有兩個元素,第一個元素是套接字對象,第二個元素是客戶端的地址(也是元組)

(<socket.socket fd=432, family=AddressFamily.AF_INET, ttype=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000), raddr=('127.0.0.1', 60925)>, ('127.0.0.1', 60925)
)

注意事項:

  • 明確自己開發的到底是客戶端還是服務端
    • 客戶端:connect()、send()、recv()、close()
    • 服務端:socket()、bind()、listen()、accept()、recv()、send()、close()
  • 兩個對象要分清楚
    • tcp_server_socket:主要用于接收客戶端連接
      • 內部只有服務器本身的信息,可以綁定端口、設置監聽、接收連接
    • new_socket:主要用于接收和發送數據
      • 內部既有客戶端又有服務器端信息,可以接收和發送數據
      • 只能通過這個新套接字來收發數據

服務器端面向對象版本

都是七步,不變

面向對象,先分析有哪些對象,創建類,屬性和方法


# 第一步:創建類
class WebServer:# 第四步:創建初始化方法,初始化套接字對象def __init__(self):# 1.創建套接字對象self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET表示IPV4,SOCK_STREAM表示TCP協議# 2.綁定ip和端口號self.tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本機,可以不寫ip地址# 這里的8000端口不會隨著服務器關閉而釋放,需要設置端口復用,端口復用在下一篇筆記# 3.設置監聽self.tcp_server_socket.listen(128)  # 128表示最大連接數# 第五步:定義一個start方法,啟動服務器,接收客戶端連接def start(self):while True:# 4.等待接受客戶端的連接請求new_socket, ip_port = self.tcp_server_socket.accept()# 5.接收數據recv_data = new_socket.recv(1024).decode("utf-8")print(f"接收到的數據為:{recv_data}")# 6.發送數據new_socket.send("信息已收到".encode("utf-8"))# 7.關閉套接字(只能接收一次信息)# 不能關閉tcp_server_socket,否則無法繼續接收新連接new_socket.close()# 目前一次只能接收一個客戶端,因為是單進程# 如果希望服務器可以同時和多個客戶端收發消息,需要多進程(多任務編程)# 第二步:實例化對象
ws = WebServer()# 第三步:調用start方法,啟動服務器,接收客戶端連接
ws.start()

端口復用

在上一次關閉服務器后,端口不會立即釋放,需要設置端口復用,才能繼續使用此端口

import socketclass WebServer:# 3、定義一個__init__方法,初始化套接字對象def __init__(self):self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設置端口復用(在上一次關閉服務器后,端口不會立即釋放,需要設置端口復用)self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)  # 參數2:SOL_SOCKET表示當前套接字對象,參數3:SO_REUSEADDR表示復用的地址,參數4:True表示開啟端口復用(默認是false,要等待很長時間端口才會自動釋放)self.tcp_server_socket.bind(("127.0.0.1", 8000))  # 如果是本機,可以不寫ip地址self.tcp_server_socket.listen(128)  # 128表示最大連接數# 4、定義一個start方法,啟動服務器,接收客戶端連接def start(self):while True:# 等待接受客戶端的連接請求new_socket, ip_port = self.tcp_server_socket.accept()# 調用自身的handle_request()方法,用于接收和發送消息(封裝性)self.handle_request(new_socket, ip_port)# 5、定義一個handle_request方法,用于接收和發送消息def handle_request(self, new_socket, ip_port):# 接收某個客戶端發送過來的消息recv_data = new_socket.recv(1024).decode("utf-8")  # 實際工作中一條數據大小在1~1.5k之間print(f"接收到的數據為:{recv_data}")# 發送消息給客戶端new_socket.send("信息已收到".encode("utf-8"))# 關閉套接字new_socket.close()# 定義一個程序的執行入口
if __name__ == "__main__":# 1、實例化服務器對象server = WebServer()# 2、啟動服務器server.start()

開發注意事項

1.當TCP客戶端程序想要和TCP服務端程序進行通信的時候必須要先建立連接
2.TCP客戶端程序一般不需要綁定端口號,因為客戶端是主動發起建立連接的。
3.TCP服務端程序必須綁定端口號,否則客戶端找不到這個TCP服務端程序。
4.listen后的套接字是被動套接字,只負責接收新的客戶端的連接請求,不能收發消息。
5.當TCP客戶端程序和TCP服務端程序連接成功后,TCP服務器端程序會產生一個新的套接字,收發客戶端消息使用該套接字。
6.關閉accept返回的套接字意味著和這個客戶端已經通信完畢。
7.當客戶端的套接字調用close后,服務器端的recv會解阻塞,返回的數據長度為O,服務端可以通過返回數據的長度來判斷客戶端是否
已經下線,反之服務端關閉套接字,客戶端的recv也會解阻塞,返回的數據長度也為0。

UDP客戶端

# 導入socket模塊
import socket# 創建UDP套接字對象
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 連接服務器,發送數據
udp_socket.sendto("消息".encode("utf-8"), ("127.0.0.1", 8000))# 關閉套接字
udp_socket.close()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63949.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63949.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63949.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es 中 terms set 使用

在 Elasticsearch 中&#xff0c;terms_set 查詢通常用于在一個字段上進行多值匹配&#xff0c;并支持設置一個條件&#xff08;例如最小匹配數量&#xff09;&#xff0c;讓查詢結果更具靈活性。為了展示如何使用 terms_set 查詢&#xff0c;我們首先會創建一個索引&#xff0…

修改采購訂單BAPI學習研究-BAPI_PO_CHANGE

這里是修改采購訂單BAPI&#xff0c;修改訂單數量和交貨日期的簡單應用 文章目錄 修改數量代碼運行結果 修改交貨日期代碼運行結果 修改數量 代碼 *&---------------------------------------------------------------------* *& Report Z_BAPI_PO_CHANGE *&----…

WSL2高級配置之mirrored鏡像網絡

WSL2高級配置之mirrored鏡像網絡 引言版本要求更改配置 引言 WSL2默認的網絡模式為NAT。盡管WSL2原生提供了localhost轉發這種能夠方便地在Windows中訪問子系統服務的特性&#xff0c;但如果想反過來&#xff0c;則只能通過局域網或者想辦法橋接&#xff0c;這兩種方法都有些許…

《ROS2 機器人開發 從入門道實踐》 魚香ROS2——第4章內容

第4章 服務和參數——深入ROS2通信 4.2 用Python服務通信實現人臉檢測 4.2.1 自定義服務接口 1. 創建接口功能包 終端中輸入 ros2 pkg create chapt4_interfaces --dependencies sensor_msgs rosidl_default_generators --license Apache-2.0 ros2 pkg create 功能包名稱…

Linux系統編程深度解析:C語言實戰指南

文章一覽 前言一、gcc編譯系統1.1 文件名后綴1.2 C語言編譯過程1.3 gcc命令行選項 二、gdb程序調試工具2.1 啟動gdb和查看內部命令2.2 顯示源程序和數據2.2.1 顯示和搜索源程序2.2.2 查看運行時數據 2.3 改變和顯示目錄或路徑2.4 控制程序的執行2.4.1 設置斷點2.4.2 顯示斷點2.…

SQL優化原理與具體實例分析

一、引言 SQL&#xff08;Structured Query Language&#xff0c;結構化查詢語言&#xff09;是關系型數據庫的核心語言。在實際應用中&#xff0c;數據庫查詢性能往往成為系統性能瓶頸。因此&#xff0c;掌握SQL優化技巧對于提高數據庫查詢效率具有重要意義。本文將圍繞SQL優…

安卓藍牙掃描流程

目錄 系統廣播 流程圖 源碼跟蹤 系統廣播 掃描開啟廣播&#xff1a;BluetoothAdapter.ACTION_DISCOVERY_STARTED "android.bluetooth.adapter.action.DISCOVERY_STARTED";掃描關閉廣播&#xff1a;BluetoothAdapter.ACTION_DISCOVERY_FINISHED "android.b…

shell 編程(三)

條件測試命令 條件測試&#xff1a;判斷某需求是否滿足&#xff0c;需要有測試機制來實現 專用的測試表達式需要由測試命令輔助完成測試過程&#xff0c;評估布爾生命&#xff0c;以便用在條件性執行中 若真,則狀態碼變量$? 返回0 // echo $? 打印0 反之返回1 t…

八股(One Day one)

最近老是看到一些面試的視頻&#xff0c;對于視頻內部面試所提到的八股文&#xff0c;感覺是知道是什么&#xff0c;但是要說的話&#xff0c;卻又不知道該怎么說&#xff08;要不咋稱之為八股文呢&#xff09;&#xff0c;所以就想到寫一篇八股文總結的博客&#xff0c;以便進…

Rust 在前端基建中的使用

摘要 隨著前端技術的不斷發展&#xff0c;前端基礎設施&#xff08;前端基建&#xff09;的建設已成為提升開發效率、保障產品質量的關鍵環節。然而&#xff0c;在應對復雜業務場景與高性能需求時&#xff0c;傳統的前端技術棧逐漸暴露出諸多不足。近年來&#xff0c;Rust語言…

豆包MarsCode:a替換函數

問題描述 思路分析 在這個問題中&#xff0c;我們的目標是將字符串中的所有小寫字母 a 替換為 "%100"。為了實現這一點&#xff0c;我們需要分析問題的核心需求和合理的解決方案。以下是分析和思路的詳細步驟&#xff1a; 1. 理解問題 給定一個字符串 s&#xff0…

人臉生成3d模型 Era3D

從單視圖圖像進行3D重建是計算機視覺和圖形學中的一項基本任務&#xff0c;因為它在游戲設計、虛擬現實和機器人技術中具有潛在的應用價值。早期的研究主要依賴于直接在體素上進行3D回歸&#xff0c;這往往會導致過于平滑的結果&#xff0c;并且由于3D訓練數據的限制&#xff0…

【點估計】之Python實現

點估計是一種統計推斷方法,它利用樣本數據來估計總體的未知參數。在概率論和數理統計的框架下,點估計將總體的未知參數視為一個確定的值或一個具體的點,并試圖通過樣本數據來找到這個值的最佳估計。以下是對點估計的詳細解釋: 一、定義與原理 定義:點估計是根據樣本數據估…

rust與python互通

互通三件套 rust側與python互通的三個庫&#xff1a; pyo3 pythonize serde pyo3 pyo3跟用Python C API寫python擴展有點類似&#xff0c;核心是&#xff1a; #[pymodule] #[pyfunction]兩個注解。前者對應Py_InitModule&#xff0c;后者對應PyMethodDef。 下面是其它博…

Ubuntu系統下 npm install -g tauri 報錯問題處理

處理在安裝 Tauri 時遇到的問題&#xff0c;可以按照以下步驟進行操作 npm install -g taurinpm warn deprecated inflight1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async …

信貸域——互聯網金融理論基礎

摘要 互聯網金融這種新興的金融業態近幾年飛速發展&#xff0c;規模不斷擴大&#xff0c;互聯網金融在對我國金融體系和經濟發展影響中所占的分量越來越重&#xff0c;一定程度上也推動了互聯網金融理論的發展。 互聯網金融與傳統金融都是金融&#xff0c;有著相近的理論基礎。…

C++軟件設計模式之享元模式(FlyWeight)

享元&#xff08;Flyweight&#xff09;模式的動機與意圖 動機 享元模式的主要動機是通過共享對象來減少內存使用&#xff0c;從而提高系統的性能。在某些情況下&#xff0c;系統中可能有大量細粒度的對象&#xff0c;這些對象具有共同的部分狀態&#xff0c;而這些狀態可以共…

LightGBM分類算法在醫療數據挖掘中的深度探索與應用創新(上)

一、引言 1.1 醫療數據挖掘的重要性與挑戰 在當今數字化醫療時代,醫療數據呈爆炸式增長,這些數據蘊含著豐富的信息,對醫療決策具有極為重要的意義。通過對醫療數據的深入挖掘,可以發現潛在的疾病模式、治療效果關聯以及患者的健康風險因素,從而為精準醫療、個性化治療方…

|-牛式-|

題目描述 下面是一個乘法豎式&#xff0c;如果用我們給定的那幾個數字來取代 * &#xff0c;可以使式子成立的話&#xff0c;我們就叫這個式子牛式。 * * * x * * ------- * * * * * * ------- * * * * 數字只能取代 * &#xff0c;當然第一位不能為 0 。 寫一個程序找…

es 3期 第18節-分頁查詢使用避坑的一些事

#### 1.Elasticsearch是數據庫&#xff0c;不是普通的Java應用程序&#xff0c;傳統數據庫需要的硬件資源同樣需要&#xff0c;提升性能最有效的就是升級硬件。 #### 2.Elasticsearch是文檔型數據庫&#xff0c;不是關系型數據庫&#xff0c;不具備嚴格的ACID事務特性&#xff…