初識socket

来源:https://www.cnblogs.com/caesar-id/archive/2019/12/17/12057502.html
-Advertisement-
Play Games

一、初識socket socket(套接字)起源於20世紀70年代加利福尼亞大學伯克利分校版本的Unix,即人們所說的BSDUnix。因此,有時人們也把套接字稱為“伯克利套接字”或“BSD套接字”。一開始,套接字被設計用在同一臺主機上多個應用程式之間的通訊。這也被稱進程間通訊,或IPC。socket ...


一、初識socket

       socket(套接字)起源於20世紀70年代加利福尼亞大學伯克利分校版本的Unix,即人們所說的BSDUnix。因此,有時人們也把套接字稱為“伯克利套接字”或“BSD套接字”。一開始,套接字被設計用在同一臺主機上多個應用程式之間的通訊。這也被稱進程間通訊,或IPC。socket(套接字)也可用在相同或者不同的設備進程之間進行通信。

       套接字(socket)是一個抽象層,應用程式可以通過它發送或接收數據,可對其進行像對文件一樣的打開、讀寫和關閉等操作。套接字允許應用程式將I/O插入到網路中,並與網路中的其他應用程式進行通信。網路套接字是IP地址與埠的組合。

       為了滿足不同的通信程式對通信質量和性能的要求,一般的網路系統提供了三種不同類型的套接字,以供用戶在設計網路應用程式時根據不同的要求來選擇。這三種套接為流式套接字(SOCK-STREAM)、數據報套接字(SOCK-DGRAM)和原始套接字(SOCK-RAW)。

流式套接字:它提供了一種可靠的、面向連接的雙向數據傳輸服務,實現了數據無差錯、無重覆的發送。流式套接字內設流量控制,被傳輸的數據看作是無記錄邊界的位元組流。在TCP/IP協議簇中,使用TCP協議來實現位元組流的傳輸,當用戶想要發送大批量的數據或者對數據傳輸有較高的要求時,可以使用流式套接字。

數據報套接字:它提供了一種無連接、不可靠的雙向數據傳輸服務。數據包以獨立的形式被髮送,並且保留了記錄邊界,不提供可靠性保證。數據在傳輸過程中可能會丟失或重覆,並且不能保證在接收端按發送順序接收數據。在TCP/IP協議簇中,使用UDP協議來實現數據報套接字。在出現差錯的可能性較小或允許部分傳輸出錯的應用場合,可以使用數據報套接字進行數據傳輸,這樣通信的效率較高。

原始套接字:該套接字允許對較低層協議(如IP或ICMP)進行直接訪問,常用於網路協議分析,檢驗新的網路協議實現,也可用於測試新配置或安裝的網路設備。
軟體開發架構一般分為C/S和B/S兩種。

  • C/S:Client與Server ,中文意思:客戶端與伺服器端架構
  • B/S:Browser與Server,中文意思:瀏覽器端與伺服器端架構

二、socket.socket()模塊簡介

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
初始化參數:
family:套接字有很多家族,AF_INET,AF_UNIX ,AF_IRDA,等多種,我們先學習AF_INET,預設是AF_INET。
AF_UNIX:是基於文件類型的套接字家族,unix一切皆文件,基於文件的套接字調用的就是底層的文件系統來取數據,兩個套接字進程運行在同一機器,可以通過訪問同一個文件系統間接完成通信。
AF_INET:是基於網路類型的套接字家族(還有AF_INET6被用於ipv6,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由於我們只關心網路編程,所以大部分時候我們只使用AF_INET)
type:套接字類型有如下幾種:預設是SOCK_STREAM。

  • SOCK_STREAM:TCP流(常用)
  • SOCK_DGRAM¶:UDP數據報(常用)
  • SOCK_RAW:原始套接字(常用)
  • SOCK_RDM:保證交付數據報但不保證順序。
  • SOCK_SEQPACKET:可靠的連續數據包服務

proto:埠號通常為0,這樣socket會隨機使用一個沒被占用的埠,在能確定埠沒被占用的情況下可以手動指定埠號,在地址家族為AF_CAN的情況下,協議應該是CAN_RAW、CAN_BCM或CAN_ISOTP之一。
fileno:從指定的文件描述符中自動檢測family,type和proto的值。預設是None。

三、socket object常用方法:

socket.bind(address):將socket綁定一個地址,這個socket必須沒有綁定過。

socket.listen([backlog]):socket伺服器進入監聽模式以接受連接。如果指定了backlog這個值最少為0。backlog代表沒有被 accept 取走的連接數量。如果未指定,系統會選擇預設的合理值。

socket.accept():接受一個連接。socket必須綁定到一個地址並監聽連接。返回值是一個元組(conn,address),其中conn是一個新的套接字對象,用於在連接上發送和接收數據,address是綁定到連接另一端套接字的地址。

socket.recv(bufsize):接收發送過來的數據。 返回值是一個位元組對象,一次接收的最大數據量由bufsize指定。為了與硬體和網路實際情況保持最佳匹配,bufsize的值應為2的次冪,例如1024,2047,4096等。

socket.recvfrom(bufsize):接收數據。返回值是一個元組(位元組,地址),其中位元組是一個位元組對象,表示接收到的數據,地址是發送數據的socket的地址。

socket.recvmsg(bufsize,ancbufsize,):從套接字接收數據和輔助數據。bufsize(位元組)接收數據的大小ancbufsize參數設置用於接收輔助數據的內部緩衝區的大小(以位元組為單位)。它預設為0,表示將不會接收任何輔助數據。可以使用CMSG_SPACE()或CMSG_LEN()計算輔助數據的適當緩衝區大小,不適合緩衝區的項目可能會被截斷或丟棄。返回值是一個四元組:(數據,ancdata,msg_flags,address)。數據項是一個位元組對象,ancdata項是零個或多個元組(cmsg_level,cmsg_type,cmsg_data)的列表,表示接收到的輔助數據(控制消息):cmsg_level和cmsg_type是分別指定協議級別和協議特定類型的整數,而cmsg_data是位元組對象保存相關數據。 msg_flags項是指示接收消息條件的各種標誌的按位或;有關詳細信息,請參見系統文檔。如果接收套接字未連接,則address是發送套接字的地址(如果有);否則,其值未指定。

socket.send(bytes):將數據發送到socket。該socket必須連接到遠程socket。返回發送的位元組數。

socket.sendall(bytes):與send()類似不同的是此方法繼續從位元組發送數據,直到所有數據都已發送或發生錯誤為止。 成功不返回任何內容。 如果出錯,則會引發異常,所以無法確定成功發送了多少數據。

socket.sendto(bytes,address):將數據發送到socket。不應連接到遠程socket,因為目標socket是按地址指定的。返回發送的位元組數。

socket.connect(address):根據地址連接遠程socket。

socket.fileno():返回socket的文件描述符(一個小整數),如果失敗則返回-1。這對於select.select()非常有用。在Windows下,這個方法返回的小整數不能用於可以使用文件描述符的地方(例如os.fdopen())。Unix沒有這個限制。

socket.getpeername():返回socket連接到的遠程地址,埠號。在某些系統上,可能不支持此功能。

socket.getsockname():返回自己socket的地址和埠號。

socket.getblocking():如果套接字處於阻塞模式,則返回True;如果處於非阻塞模式,則返回False。適用於Python3.7。

socket.shutdown(how):關閉連接。如果how=SHUT_RD則不允許接收數據。如果how=SHUT_WR則不允許發送數據。如果how=SHUT_RDWR如何,則不允許發送和接收。

socket.close():釋放與連接關聯的資源,但不一定立即關閉連接,套接字對象上的所有後續操作都將失敗。遠程端將不再接收任何數據。如果希望及時關閉連接,在close()之前調用shutdown()。

socket.detach():關閉socket對象而不,而不實際關閉底層文件描述符。返迴文件描述符,此調用後無法使用socket對象,但可以使用文件描述符,用於其他目的。

 

socket.settimeout(value):設置socket阻塞模式下超時時間。value值是非負數(單位:秒),如果給出了value,在value秒後還沒有接收到數據,連接請求,將引發超時異常。如果給定0,則套接字將處於非阻塞模式。如果是None,套接字將進入阻塞模式。

參考文檔: https://docs.python.org/3/library/socket.html?highlight=socket#socket.AF_INET。

 

四、簡單示例

建立基本的連接

server端:

import socket
server_obj = socket.socket()              # 創建socket對象
server_obj.bind(("socket伺服器地址",9000))  # socket綁定IP地址和監聽埠
server_obj.listen(5)                      # 監聽遠程socket連接
con,addr = server_obj.accept()            # 建立socket連接
msg = con.recv(1024).decode("utf-8")      # 接收遠程socket發來的數據
print(msg)
con.send(msg.upper().encode("utf-8"))     # 發送數據給遠程socket
con.close()         # 關閉連接
server_obj.close()  # 關閉連接

client端:

import socket
client = socket.socket()                # 創建socket對象
client.connect(("遠程socket地址",9000))  # 連接遠程socket
msg = input(">>>")
client.send(msg.encode("utf-8"))             # 發送數據給遠程socket
recv_msg = client.recv(1024).decode("utf-8") # 接收遠程socket發來的數據
print(recv_msg)
client.close()  # 關閉socket

上面的示例只能收一次,發一次消息,然後就結束了。下麵我們使用while迴圈,來迴圈收,發消息。

server端:

import socket
server_obj = socket.socket()              # 創建socket對象
server_obj.bind(("192.168.10.102",9000))  # socket綁定地址和埠
server_obj.listen(5)                      # 監聽socket連接請求
con,addr = server_obj.accept()            # 建立socket連接
print('遠端socket對象:',con.getpeername()) # 列印遠程socket信息
while True:
    try:
        msg = con.recv(1024)  # 接收遠程socket發來的數據
        if msg.decode('utf-8').upper()=='Q':break # 如果發來的是q表示斷開連接
        print(msg.decode("utf-8"))
        con.send('我接到了你發來的消息'.encode('utf-8'))
    except Exception:
        break
print(連接已斷開)
con.close()
server_obj.close()

client端:

import socket
client = socket.socket()                # 創建socket對象
client.connect(("192.168.10.102",9000)) # 連接遠程socket
while True:
    msg = input(">>>")
    if msg.upper() == 'Q':break       # 輸入q退出程式
    client.send(msg.encode("utf-8"))  # 發送數據給遠程socket
    recv_msg = client.recv(1024).decode("utf-8") # 接收遠程socket發來的數據
    print(recv_msg)
print('退出程式')
client.close()

此時我們的伺服器只能接受一個客戶端的連接,如果客戶端斷開了,服務端將關閉。如果想讓伺服器一直接受請求一個客戶端斷開連接後,繼續接受下一個客戶端的連接,看如下server代碼:

import socket
server_obj = socket.socket()              # 創建socket對象
server_obj.bind(("192.168.10.102",9000))  # socket綁定地址和埠
server_obj.listen(5)                      # 監聽socket連接請求
while 1:
    print('等待接收遠程socket連接......')
    con,addr = server_obj.accept()        # 建立socket連接
    print('連接一臺遠程socket:',con.getpeername())
    while True:
        try:
            msg = con.recv(1024)          # 接收遠程socke
            if msg.decode('utf-8').upper()=='Q':break
            print(msg.decode("utf-8"))
            con.send('我接到了你發來的消息'.encode('utf-8'))
        except Exception:
            break
    con_address,con_port = con.getpeername() # 獲取斷開socke對象信息
    print(con_address,'斷開了連接')
    con.close()
server_obj.close()

關於recv要註意的地方:

當緩衝區沒有數據可取時,recv會一直處於阻塞狀態,直到緩衝區至少有一個位元組數據可取,或者遠程端關閉。關閉遠程端並讀取所有數據後,返回空字元串。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript 錯誤 - Throw 和 Try to Catch try 語句使您能夠測試代碼塊中的錯誤。 catch 語句允許您處理錯誤。 throw 語句允許您創建自定義錯誤。 finally 使您能夠執行代碼,在 try 和 catch 之後,無論結果如何。 錯誤總會發生! 當執行 J ...
  • 本書內容 本書從書名就可以看出來,講了架構的兩個東西,一個是原理,一個是案例。 案例部分沒有在導圖中體現,不過建議讀者還是要看一下案例,能夠通過案例對原理有更加深刻的印象 推薦程度 4.5 顆星 推薦原因 通讀本書,能對大型網站有更加直觀的感受 細節之處,能夠指導你設計網站架構選用的具體方案 即使以 ...
  • 在k8s里,你可以通過服務名去訪問相同namespace里的服務,然後服務可以解析到對應的pod,從而再由pod轉到對應的容器里,我們可以認為這個過程有兩個port的概念,service port 就是服務的port,在k8s配置文件里用 表示,還有一個是pod和容器的port,用targetPor ...
  • PHP 7.4.0 發佈了,此版本標志著 PHP 7 系列的第四次特性更新。 看了英文手冊後,發現其進行了許多改進,並帶來了一些新特性,現在將這些新特性您: 1.Typed Properties 類型屬性 類屬性現在支持類型聲明,以下示例將強制 $User-> id 只能分配 int 值,而 $Us ...
  • 首先介紹一下Java的各個層級,先放一張圖: 硬體,操作系統和操作系統介面:這三級不說大家都知道,操作系統有很多種,比如Windows,Linux。Windows又分為win7,win10,win xp等等;Linux有Ubuntu,CentOS;操作系統介面就是系統為開發者預留的,方便調用從而控制 ...
  • 之前的aop是通過手動創建代理類來進行通知的,但是在日常開發中,我們並不願意在代碼中硬編碼這些代理類,我們更願意使用DI和IOC來管理aop代理類。Spring為我們提供了以下方式來使用aop框架 一、以聲明的方式配置AOP(就是使用xml配置文件) 1.使用ProxyFactoryBean的方式: ...
  • tcp傳輸的數據是以流的形式傳輸的,因此就沒有辦法判斷到哪裡結束算是自己的一個消息,這樣就會出現粘包問題,多個包粘在一起了 可以使用這樣一個自定義的形式來解決,一個消息分為 head+body head包括數據的長度和數據編號 , 長度和編號都是uint32類型 也就是32位 占有4個位元組 , 總共 ...
  • Shiro是一個功能強大且易於使用的Java安全框架,主要功能有身份驗證、授權、加密和會話管理。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...