Skynet.socket 函數族使用詳解

在這里插入圖片描述

目錄

  • Skynet.socket 函數族使用詳解
  • 核心功能分類
  • 一、TCP 連接管理
    • 1. 監聽端口
    • 2. 建立連接
    • 3. 關閉連接
  • 二、數據讀寫操作
    • 1. 阻塞式讀取
    • 2. 寫入數據
      • 2.1 `socket.write(fd, data)` 的返回值
      • 2.2 示例代碼
      • 2.3 關鍵注意事項
      • 2.4 與其他函數的區別
      • 2.5 底層原理
      • 2.6 總結
  • 三、UDP 處理
    • 1. 創建 UDP 句柄
    • 2. 發送 UDP 數據
  • 四、高級控制與監控
    • 1. 緩沖區過載警告
    • 2. 域名解析
  • 五、SocketChannel 封裝
    • 1. 創建 Channel 對象
    • 2. 發送請求
  • 六、最佳實踐與注意事項
  • 總結

Skynet.socket 函數族使用詳解

Skynet 的 skynet.socket 模塊提供了 TCP/UDP 網絡通信的核心 API,結合協程機制實現了阻塞式調用模型,簡化了異步網絡編程。本文詳細解析其核心函數、使用場景及最佳實踐。


核心功能分類

  1. TCP 連接管理(監聽、連接、關閉)
  2. 數據讀寫(阻塞式讀寫、分包處理)
  3. UDP 支持(數據包收發、地址管理)
  4. 高級控制(緩沖區警告、域名解析、過載處理)

一、TCP 連接管理

1. 監聽端口

local socket = require "skynet.socket"-- 啟動 TCP 服務器
skynet.start(function()local listen_fd = socket.listen("0.0.0.0", 8888) -- 監聽 8888 端口socket.start(listen_fd, function(client_fd, addr)-- 新連接回調,處理客戶端請求socket.start(client_fd)-- ... 處理數據邏輯end)
end)
  • socket.listen(host, port [, backlog])
    返回監聽套接字的文件描述符 listen_fd
    backlog:等待連接隊列的最大長度(可選,默認 SOMAXCONN)。

2. 建立連接

local client_fd = socket.open("127.0.0.1", 6379) -- 連接 Redis
if client_fd thensocket.start(client_fd)socket.write(client_fd, "PING\r\n")
end
  • socket.open(host, port)
    同步阻塞連接目標地址,返回客戶端套接字 client_fd

3. 關閉連接

socket.close(client_fd)  -- 安全關閉,等待未完成讀寫
socket.close_fd(client_fd) -- 強制立即關閉(慎用)
socket.shutdown(client_fd) -- 強制關閉(適用于 __gc 元方法)
  • 區別
    • close:等待其他協程完成讀寫后關閉。
    • close_fd/shutdown:直接關閉,可能導致未處理數據丟失。

二、數據讀寫操作

1. 阻塞式讀取

-- 讀取固定字節
local data, partial = socket.read(client_fd, 1024) -- 讀 1024 字節
if data thenprint("完整數據:", data)
elseprint("部分數據:", partial) -- 連接已關閉
end-- 讀取一行(默認以 \n 分割)
local line = socket.readline(client_fd, "\r\n") -- 自定義分隔符
  • socket.read(fd, sz)
    • sznil 時讀取盡可能多的數據(至少 1 字節)。
    • 返回完整數據或 false + 已讀部分數據(連接關閉時)。

2. 寫入數據

socket.write(client_fd, "Hello Skynet!\r\n") -- 高優先級寫入
socket.lwrite(client_fd, "Low priority data\r\n") -- 低優先級寫入
  • 優先級區別
    • write:數據進入高優先級隊列,優先發送。
    • lwrite:數據進入低優先級隊列,高優先級隊列為空時發送。
      在 Skynet 框架中,socket.write 方法的返回值取決于數據是否成功寫入內核的發送緩沖區。以下是具體說明:

2.1 socket.write(fd, data) 的返回值

  1. 成功時

    • 返回 true,表示數據已成功加入內核的發送隊列,不保證對端已接收
    • 注意:返回值僅表示數據成功提交到操作系統的網絡協議棧,實際網絡傳輸是異步的。
  2. 失敗時

    • 返回 nil + 錯誤信息(如 "closed" 表示連接已關閉)。
    • 常見錯誤:
      • "closed": 連接已關閉。
      • "timeout": 發送超時(需結合 socketdriver.settimeout 設置)。
      • "error": 其他底層錯誤。

2.2 示例代碼

local skynet = require "skynet"
local socket = require "skynet.socket"local fd = ...  -- 假設 fd 是已建立的客戶端連接-- 嘗試發送數據
local ok, err = socket.write(fd, "Hello World")
if not ok thenskynet.error("Send failed:", err)socket.close(fd)  -- 關閉失效連接
end

2.3 關鍵注意事項

  1. 異步發送socket.write 是非阻塞的,數據可能仍在發送隊列中未實際傳輸。
  2. 流量控制:若發送速度超過網絡帶寬或對端接收速度,可能導致緩沖區積壓,最終觸發錯誤。
  3. 錯誤處理:務必檢查返回值,及時關閉失效的 fd,避免資源泄漏。
  4. 大包分片:單次寫入數據過大可能被系統拆分,需結合業務邏輯處理完整性(如添加長度頭)。

2.4 與其他函數的區別

  • socket.send:與 socket.write 行為一致,兩者是別名關系。
  • socket.lwrite:專用于發送 Lua 字符串(內部優化),行為相同。

2.5 底層原理

Skynet 的 socket.write 最終調用操作系統的 send 系統調用,但通過非阻塞模式封裝。若內核發送緩沖區已滿,數據會排隊等待,此時返回 true;若連接已異常(如對端關閉),則直接返回錯誤。


2.6 總結

  • 返回值意義true 表示數據提交成功,nil + err 表示失敗。
  • 必須處理錯誤:尤其要捕獲 "closed" 錯誤,及時清理連接狀態。
  • 性能影響:高頻發送時建議結合 socketdriver.setqueue_max 控制緩沖區大小,避免內存暴漲。

三、UDP 處理

1. 創建 UDP 句柄

local udp_fd = socket.udp(function(data, from)print("收到 UDP 數據:", data, "來源:", socket.udp_address(from))
end, "0.0.0.0", 9999) -- 綁定 9999 端口
  • socket.udp(callback [, host, port])
    創建 UDP 句柄并綁定回調,收到數據時觸發 callback(data, from)

2. 發送 UDP 數據

socket.sendto(udp_fd, from_address, "ACK") -- 發送到指定地址
socket.write(udp_fd, "Ping") -- 若已設置默認地址,直接寫入
  • socket.sendto(fd, from, data)
    from 為接收到的來源地址字符串,不可手動構造。

四、高級控制與監控

1. 緩沖區過載警告

socket.warning(client_fd, function(fd, size)if size > 0 thenprint("警告:待發數據超過", size, "KB")elseprint("緩沖區已清空")end
end)
  • socket.warning(fd, callback)
    監控待發數據量,超過 1MB 觸發回調(默認每超 64KB 打印錯誤日志)。

2. 域名解析

local dns = require "skynet.dns"
dns.server("8.8.8.8") -- 設置 DNS 服務器
local ip, all_ips = dns.resolve("www.example.com") -- 解析域名
  • dns.resolve(name [, ipv6])
    返回解析到的 IP 地址及所有 IP 列表,避免阻塞 socket 線程。

五、SocketChannel 封裝

1. 創建 Channel 對象

local sc = require "skynet.socketchannel"
local channel = sc.channel {host = "127.0.0.1",port = 6379,response = function(sock)return true, sock:readline("\r\n") -- 解析 Redis 響應end,
}
  • 模式選擇
    • 提供 response 函數則進入 Session 模式(如 MongoDB)。
    • 否則為 請求-回應模式(如 Redis)。

2. 發送請求

local resp = channel:request("PING\r\n") -- 請求并等待響應
local resp2 = channel:request("GET key\r\n", function(sock)return true, sock:read(5) -- 自定義響應解析
end)
  • channel:request(req [, response | session])
    發送請求并自動匹配響應,支持自定義解析邏輯。

六、最佳實踐與注意事項

  1. 連接生命周期管理

    • 使用 socket.close 確保安全關閉。
    • 避免在 __gc 中使用阻塞操作,優先用 shutdown
  2. 協程調度優化

    • 高頻讀寫時,合理使用 socket.lwrite 避免阻塞關鍵數據。
    • 結合 skynet.fork 處理并發請求。
  3. 錯誤處理

    • 所有讀寫操作需包裹在 pcall 中捕獲異常。
    • UDP 需處理亂序和丟包,不可依賴時序。
  4. 性能監控

    • 使用 socket.warning 監控緩沖區,防止內存溢出。
    • 避免頻繁 DNS 查詢,通過緩存或獨立服務處理。

總結

skynet.socket 通過協程化阻塞 API 簡化了網絡編程復雜度,結合 socketchannel 可高效處理復雜協議。開發者需注意:

  • 連接安全性:合理關閉連接,避免資源泄漏。
  • 協議適配:根據場景選擇基礎 API 或高級封裝。
  • 性能調優:監控緩沖區,平衡吞吐量與內存消耗。

通過閱讀 lualib/socket.lua 和參考 service/gate.lua,可深入理解底層實現機制。

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

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

相關文章

Unity Addressables資源生命周期自動化監控技術詳解

一、Addressables資源生命周期管理痛點 1. 常見資源泄漏場景 泄漏類型典型表現檢測難度隱式引用泄漏腳本持有AssetReference未釋放高異步操作未處理AsyncOperationHandle未釋放中循環依賴泄漏資源相互引用無法釋放極高事件訂閱泄漏未取消事件監聽導致對象保留高 2. 傳統管理…

aws(學習筆記第三十八課) codepipeline-build-deploy-github-manual

文章目錄 aws(學習筆記第三十八課) codepipeline-build-deploy-github-manual學習內容:1. 整體架構1.1 代碼鏈接1.2 全體處理架構2. 代碼分析2.1 創建`ImageRepo`,并設定給`FargateTaskDef`2.2 創建`CodeBuild project`2.3 對`CodeBuild project`賦予權限(`ECR`的`image rep…

在windows服務器使用Nginx反向代理云端的python實現的web應用

近日得閑,計劃將之前寫過的一些小桌面程序搬到云服務器上方便隨時隨地使用,同時也學習一些基本的網站開發和搭建知識,于是在AI的幫助下,基于niceguifastapi非常快捷地搞出來了一個前后端一體的網站程序,放在云服務器上…

全球貿易戰火重燃:50%關稅如何絞殺跨境電商低價模式?

一、政策高壓:美國對華貿易戰升級路線圖 2024年5月,美國國會《數字貿易壁壘法案》草案曝光,標志著中美貿易博弈進入新階段: ? 關稅武器精準打擊:成衣、消費電子、小家電稅率擬從10-25%躍升至50% ? 監管范圍擴大&…

0411 | 軟考高項筆記:項目立項

在軟考的項目管理知識體系中,技術可行性和經濟可行性是項目立項階段非常重要的兩個分析維度。以下是對這兩個考點的詳細解釋和記憶方法: 技術可行性分析 定義: 技術可行性分析是評估項目在現有技術條件和資源下是否能夠成功實施。它主要回答…

二分查找3:69. x 的平方根

鏈接:69. x 的平方根 - 力扣(LeetCode) 題解: 本題本質是二分查找右端點 x的算數平方根一定在1 ~ x 區間內,在1 ~ x區間內查找一個數num,num^2x,但實際上num不一定是整數,所以是n…

oracle大師認證證書有用嗎

專業能力的高度認可:OCM 是 Oracle認證的最高級別,是對數據庫從業人員技術、知識和操作技能的最高級認可,也是 IT 界頂級認證之一。它表明持證者具備處理關鍵業務數據庫系統和應用的能力,能夠解決最困難的技術難題和最復雜的系統故…

InnoDB 如何解決幻讀:深入解析與 Java 實踐

在數據庫事務管理中,幻讀(Phantom Read)是并發操作中常見的問題,可能導致數據一致性異常。MySQL 的 InnoDB 存儲引擎通過其事務隔離機制和多版本并發控制(MVCC),有效解決了幻讀問題。作為 Java …

【AI編程技術爆發:從輔助工具到生產力革命】

目錄 前言:技術背景與價值當前技術痛點解決方案概述目標讀者說明 一、技術原理剖析核心概念圖解關鍵技術模塊技術選型對比 二、實戰演示環境配置要求核心代碼實現運行結果驗證 三、性能對比測試方法論量化數據對比(2023年數據)結果分析 四、最…

ICRA-2025 | 視覺預測助力機器人自主導航!NavigateDiff:視覺引導的零樣本導航助理

論文:Yiran Qin 1 , 2 ^{1,2} 1,2, Ao Sun 2 ^{2} 2, Yuze Hong 2 ^{2} 2, Benyou Wang 2 ^{2} 2, Ruimao Zhang 1 ^{1} 1單位: 1 ^{1} 1中山大學, 2 ^{2} 2香港中文大學深圳校區論文標題:NavigateDiff: Visual Predictors are Ze…

【ESP32S3】GATT Server service table傳送數據到調試助手

前言 在初步學習esp32藍牙的過程中,借鑒了官方的GATT Server Service Table Example,可以在readme中看到,此demo是采用低功耗藍牙的通用屬性服務器來創建訂閱服務和特性。如果你接觸過MQTT,你會發現GATT Server這一特性和MQTT的訂…

DeepSeek :中國 AI 如何用 “小米加步槍” 逆襲硅谷

2025 年春節前夕,人工智能領域誕生了一項重大成果 ——DeepSeek 發布DeepSeek - R1 大模型。這一模型迅速引發廣泛關注,在蘋果 AppStore 中國區免費榜登頂。 DeepSeek 采用開源策略,依據寬松的 MIT 許可證,公開了模型權重、訓練方…

關稅擾動下市場波動,如何尋找確定性的長期之錨?

近期的關稅紛爭,擾動全球資本市場下行。A股市場一度大幅下跌。但隨著各大主力下場,有關部委發布有關有力措施,A股逐步穩住陣腳。 4月8日至4月10日,大盤指數連續3天上漲,上漲120多點,展現出較強的抵御關稅壁…

NeuroImage:膝關節炎如何影響大腦?靜態與動態功能網絡變化全解析

膝骨關節炎(KOA)是導致老年人活動受限和殘疾的主要原因之一。這種疾病不僅引起關節疼痛,還會顯著影響患者的生活質量。然而,目前對于KOA患者大腦功能網絡的異常變化及其與臨床癥狀之間的關系尚不清楚。 2024年4月10日,…

【KWDB 創作者計劃】KWDB 數據庫全維度解析手冊

——從原理到實踐,構建下一代數據基礎設施 ?第一章:KWDB 設計哲學與技術全景 1.1 為什么需要 KWDB? 在數據爆炸與業務場景碎片化的今天,傳統數據庫面臨三大挑戰:?擴展性瓶頸?(單機性能天花板&#xff…

一個批量文件Dos2Unix程序(Microsoft Store,開源)

這個程序可以把整個目錄的文本文件改成UNIX格式,源碼是用C#寫的。 目錄 一、從Microsoft Store安裝 二、從github獲取源碼 三、功能介紹 3.1 運行 3.2 瀏覽 3.3 轉換 3.4 轉換(無列表) 3.5 取消 3.6 幫助 四、源碼解讀 五、討論和…

std::string` 類

以下是對 std::string 類中 修改操作 和 字符串操作 的示例代碼&#xff0c;幫助你更好地理解這些函數的使用&#xff1a; 5. 修改操作 (1) operator 用于追加字符串、C 風格字符串或字符。 #include <iostream> #include <string>int main() {std::string str …

《Spring Boot+策略模式:企業級度假訂單Excel導入系統的架構演進與技術實現》

前言 在數字化時代背景下&#xff0c;訂單管理系統的高效性與靈活性成為企業競爭力的核心要素。本文檔詳細剖析了一個基于 策略模式 的度假訂單導入系統&#xff0c;通過分層架構設計實現了多源異構數據的標準化處理。系統以 Spring Boot 為核心框架&#xff0c;結合 MyBatis …

SSRF漏洞公開報告分析

文章目錄 1. SSRF | 獲取元數據 | 賬戶接管2. AppStore | 版本上傳表單 | Blind SSRF3. HOST SSRF一、為什么HOST修改不會影響正常訪問二、案例 4. Turbonomic 的 終端節點 | SSRF 獲取元密鑰一、介紹二、漏洞分析 5. POST | Blind SSRF6. CVE-2024-40898利用 | SSRF 泄露 NTL…

告別 ifconfig:為什么現代 Linux 系統推薦使用 ip 命令

告別 ifconfig&#xff1a;為什么現代 Linux 系統推薦使用 ip 命令 ifconfig 指令已經被視為過時的工具&#xff0c;不再是查看和配置網絡接口的推薦方式。 與 netstat 被 ss 替代類似。 本文簡要介紹 ip addr 命令的使用 簡介ip ifconfig 屬于 net-tools 包&#xff0c;這個…