Linux網絡:socket編程UDP

文章目錄

  • 前言
  • 一,socket
  • 二,服務端socket
    • 3-1 創建socket
    • 3-2 綁定地址和端口
    • 3-3 接收數據
    • 3-4 回復數據
    • 3-5關閉socket
    • 3-6 完整代碼
  • 三,客戶端socket
    • 3-1 為什么客戶端通常不需要手動定義 IP 和端口


前言

學習 socket 編程的意義在于:它讓你掌握計算機之間通信的核心原理,能親手實現聊天程序、文件傳輸、簡易服務器等網絡應用;同時這是理解 TCP/IP 協議、深入系統編程和進入后臺開發、分布式系統的基礎技能,也是面試和工程實踐中必不可少的知識。


一,socket

socket(套接字) 是操作系統提供的一種 通信機制,最常用于網絡通信,在編程時,你可以把它當作 特殊的文件描述符(FD),既能讀、也能寫,文件用來在本地磁盤讀寫數據,而 socket 用來在不同主機之間交換數據。你可以把 socket 看作網絡文件,只是讀寫的數據不是在磁盤上,而是發送到網絡上的另一個進程。


二,服務端socket

主要作用:接收客戶端請求并回復,服務器端使用socket分為幾個階段:創建 socket -> 綁定地址和端口 -> 等待客戶端發送數據 / 監聽連接 -> 處理數據或回復 -> 關閉 socket


3-1 創建socket

socket函數原型

int socket(int domain, int type, int protocol);
  • domain:用于選擇網絡協議協議類型一般有值:AF_INET (IPv4 網絡協議),AF_INET6 (IPv6 網絡協議),AF_UNIX/AF_LOCAL (本地進程間通信)
  • type:指定傳輸方式,主要有兩種:SOCK_STREAM 面向連接,基于字節流(TCP),SOCK_DGRAM 無連接,基于報文(UDP)
  • protocol:通常指定具體協議:0 默認協議,IPPROTO_TCP 明確選擇 TCP,IPPROTO_UDP 明確選擇 UDP

在下面的代碼示例中我們會選擇:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

創建一個UDP的套接字


3-2 綁定地址和端口

struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY; // 任意 IP
servaddr.sin_port = htons(12345);      // 端口
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));

上面的struct sockaddr_in servaddr創建一個 IPv4 地址結構體 sockaddr_in,用來保存服務端的 IP 地址和端口信息結構體定義大致如下:

struct sockaddr_in {short            sin_family;   // 地址族 (AF_INET)unsigned short   sin_port;     // 端口號struct in_addr   sin_addr;     // IP 地址char             sin_zero[8];  // 填充為與 struct sockaddr 同大小
};

解釋上述代碼:

servaddr.sin_family = AF_INET;

設置 地址族為 IPv4 (AF_INET)告訴內核這是一個 IPv4socket

servaddr.sin_addr.s_addr = INADDR_ANY; // 任意 IP

INADDR_ANY = 0.0.0.0,表示服務端 綁定本機所有可用 IP 地址,如果服務器有多個網卡,客戶端發送到任意 IP 都能被接收

servaddr.sin_port = htons(12345); // 端口

設置端口號為 12345htons = host to network short(主機字節序 → 網絡字節序),網絡通信使用 大端序,保證不同平臺可以正確解析端口

bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));

bind() socket 文件描述符 與 IP + 端口 綁定

參數解釋:

sockfd:之前 socket() 返回的文件描述符

(struct sockaddr*)&servaddr : 地址信息,強制類型轉換為通用 sockaddr

sizeof(servaddr) : 結構體大小


3-3 接收數據

char buffer[100];
struct sockaddr_in cliaddr {};
socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr * ) & cliaddr, & len);

這段代碼在一個 UDP 服務器程序中,從客戶端接收數據,存儲到 buffer 中,同時記錄客戶端的地址信息cliaddr,并返回接收的字節數n

char buffer[100];

定義一個字符數組 buffer,大小為 100 字節,用來存儲從客戶端接收的數據

struct sockaddr_in cliaddr {};

定義一個 sockaddr_in 結構體變量 cliaddr,用于存儲客戶端的地址信息(如 IP 地址和端口號)。{} 初始化所有字段為 0

socklen_t len = sizeof(cliaddr);

定義一個 socklen_t 類型的變量 len,初始化為 cliaddr 的大小(通常 16 字節,struct sockaddr_in 的大小)。


3-4 回復數據

const char* reply = "Hello Client";sendto(sockfd, reply, strlen(reply), 0, (struct sockaddr*)&cliaddr, len); // 回復

這段代碼用與服務器回復客戶端信息

其它的不再過多贅述

(struct sockaddr*)&cliaddr:客戶端地址結構體,告訴內核消息發送到哪里


3-5關閉socket

close(sockfd);

不關閉會造成資源瀉漏


3-6 完整代碼

#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>int main() {int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 創建 UDP socketif (sockfd < 0) { perror("socket"); return -1; }sockaddr_in servaddr{};servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = INADDR_ANY;servaddr.sin_port = htons(12345);bind(sockfd, (sockaddr*)&servaddr, sizeof(servaddr)); // 綁定端口char buffer[100];sockaddr_in cliaddr{};socklen_t len = sizeof(cliaddr);int n = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (sockaddr*)&cliaddr, &len); // 接收消息buffer[n] = '\0';std::cout << "Server received: " << buffer << std::endl;const char* reply = "Hi Client";sendto(sockfd, reply, strlen(reply), 0, (sockaddr*)&cliaddr, len); // 回復客戶端close(sockfd);return 0;
}

三,客戶端socket

客戶端socket代碼我直接展示出來吧,我們理解了服務端之后,客戶端是非常好理解的

#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>int main() {int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 創建 UDP socketif (sockfd < 0) { perror("socket"); return -1; }sockaddr_in servaddr{};servaddr.sin_family = AF_INET;servaddr.sin_port = htons(12345);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本機測試const char* msg = "Hello Server";sendto(sockfd, msg, strlen(msg), 0, (sockaddr*)&servaddr, sizeof(servaddr)); // 發送消息char buffer[100];socklen_t len = sizeof(servaddr);int n = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (sockaddr*)&servaddr, &len); // 接收回復buffer[n] = '\0';std::cout << "Client received: " << buffer << std::endl;close(sockfd);return 0;
}

這里的sendtorecvfrom大家應該都懂,主要是這個客戶端是如何找到服務端的重要

    sockaddr_in servaddr{};servaddr.sin_family = AF_INET;servaddr.sin_port = htons(12345);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本機測試

在這段代碼里的IP地址和端口號是找到服務端的關鍵

  • IP 地址 (127.0.0.1):告訴客戶端要把數據發送到哪個機器。127.0.0.1 表示本機,也就是服務端和客戶端在同一臺電腦。如果服務端在另一臺電腦,你就要寫它的真實 IP,例如 192.168.1.100

  • 端口號 (12345)
    服務端在這個端口上監聽數據。UDP/TCP 都是靠端口區分不同服務的,就像房子門牌號一樣。所以客戶端通過 IP, port 就能找到服務端。


3-1 為什么客戶端通常不需要手動定義 IP 和端口

客戶端的職責是 主動找服務端,在調用 sendto()時:目標地址(服務端的 IP+端口) 由程序員指定,源地址(客戶端的 IP+端口) 不寫時由內核自動分配

IP:自動選擇一塊能到達服務端的本地網卡的 IP

端口:自動分配一個 臨時端口,通常在 49152–65535 之間

客戶端什么時候需要綁定 IP+端口:如果客戶端希望 使用固定端口(比如做 P2P、游戲服務器通知端口),或者有多張網卡,必須指定 用哪張網卡的 IP 去通信,這種情況才會手動調用 bind()

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

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

相關文章

【從零到公網】本地電腦部署服務并實現公網訪問(IPv4/IPv6/DDNS 全攻略)

從零到公網&#xff1a;本地電腦部署服務并實現公網訪問&#xff08;IPv4/IPv6/DDNS 全攻略&#xff09; 適用場景&#xff1a;本地 API 服務、大模型推理服務、NAS、遠程桌面等需要公網訪問的場景 關鍵詞&#xff1a;公網 IP、端口映射、內網穿透、IPv6、Cloudflare DDNS 一、…

模塊二 落地微服務

11 | 服務發布和引用的實踐 服務發布和引用常見的三種方式&#xff1a;Restful API、XML配置以及IDL文件。今天我將以XML配置方式為例&#xff0c;給你講解服務發布和引用的具體實踐以及可能會遇到的問題。 XML配置方式的服務發布和引用流程 1. 服務提供者定義接口 服務提供者發…

C++程序員速通C#:從Hello World到數據類型

C程序員光速入門C#&#xff08;一&#xff09;&#xff1a;總覽、數據類型、運算符 一.Hello world&#xff01; 隨著.NET的深入人心,作為一個程序員&#xff0c;當然不能在新技術面前停而止步&#xff0c;面對著c在.net中的失敗,雖然有一絲遺憾&#xff0c;但是我們應該認識到…

Linux相關概念和易錯知識點(44)(IP地址、子網和公網、NAPT、代理)

目錄1.IP地址&#xff08;1&#xff09;局域網和公網①局域網a.網關地址b.局域網通信②運營商子網③公網&#xff08;2&#xff09;NAPT①NAPT過程②理解NAPT③理解源IP和目的IPa.目的IPb.源IP③最長前綴匹配④NAT技術缺陷2.代理服務&#xff08;1&#xff09;正向代理&#xf…

工業智能終端賦能自動化生產線建設數字化管理

在當今數字化浪潮的推動下&#xff0c;自動化生產線正逐漸成為各行各業提升效率和降低成本的重要選擇。隨著智能制造的深入發展&#xff0c;工業智能終端的引入不僅為生產線帶來了技術革新&#xff0c;也賦予了數字化管理新的動力。一、工業智能終端&#xff1a;一體化設計&…

【Vue2手錄06】計算屬性Computed

一、表單元素的v-model綁定&#xff08;核心場景&#xff09; v-model 是Vue實現“表單元素與數據雙向同步”的語法糖&#xff0c;不同表單元素的綁定規則存在差異&#xff0c;需根據元素類型選擇正確的綁定方式。 1.1 四大表單元素的綁定規則對比表單元素類型綁定數據類型核心…

FPGA入門-數碼管靜態顯示

19. 數碼管的靜態顯示 在許多項目設計中&#xff0c;我們通常需要一些顯示設備來顯示我們需要的信息&#xff0c;可以選擇的顯示設備有很多&#xff0c;而數碼管是使用最多&#xff0c;最簡單的顯示設備之一。數碼管是一種半導體發光器件&#xff0c;具有響應時間短、體積小、…

深入理解大語言模型(5)-關于token

到目前為止對 LLM 的描述中&#xff0c;我們將其描述為一次預測一個單詞&#xff0c;但實際上還有一個更重要的技術細 節。即 LLM 實際上并不是重復預測下一個單詞&#xff0c;而是重復預測下一個 token 。對于一個句子&#xff0c;語言模型會 先使用分詞器將其拆分為一個個 to…

視覺智能的「破壁者」——Transformer如何重塑計算機視覺范式?三大CV算法論文介紹 ViTMAESwin Transformer

當自然語言處理領域因Transformer而煥發新生時&#xff0c;計算機視覺卻長期困于卷積神經網絡的架構桎梏。直到ViT&#xff08;Vision Transformer&#xff09;的橫空出世&#xff0c;才真正打破了視覺與語言之間的壁壘。它不僅是技術的革新&#xff0c;更是范式革命的開始&…

Java 并發容器源碼解析:ConcurrentSkipListSet 行級深度剖析

Java 并發容器源碼解析&#xff1a;ConcurrentSkipListSet 行級深度剖析 本文將深入解析 Java 并發容器 ConcurrentSkipListSet 的核心源碼&#xff0c;結合流程圖、代碼注釋、設計思想、優缺點分析、業務場景、調試與優化、集成方案、高階應用等&#xff0c;幫助你系統掌握這款…

答題卡自動識別案例

目錄 1.答題卡自動批閱整體實現思路 2.關鍵技術步驟與原理 答題卡區域提取 ①輪廓檢測并排序 ②執行透視變換 ③找到每一個圓圈輪廓 ④先對所有圓圈輪廓從上到下排序 ⑤再通過循環每次只提取出五個輪廓再進行從左到右的排序 3.完整代碼 1.答題卡自動批閱整體實現思路 …

C#實現通過POST實現讀取數據

C# POST請求與MySQL數據存儲實現下面是一個完整的C#解決方案&#xff0c;用于發送POST請求、接收響應數據&#xff0c;并將數據保存到MySQL數據庫中。完整代碼實現 using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.J…

Java 字符編碼問題,怎么優雅地解決?

網羅開發&#xff08;小紅書、快手、視頻號同名&#xff09;大家好&#xff0c;我是 展菲&#xff0c;目前在上市企業從事人工智能項目研發管理工作&#xff0c;平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術&#xff0c;包括iOS、前端、Harmony OS、Java、Python等方…

STL之string類(C++)

1.string類核心定位std::string 本質是對 “字符序列” 的封裝&#xff0c;內部通過動態數組存儲字符&#xff0c;并自動管理內存&#xff08;分配、擴容、釋放&#xff09;&#xff0c;對外提供了簡潔的接口用于字符串的創建、修改、拼接、查找等操作。1.1 使用前提頭文件包含…

[Maven 基礎課程]第一個 Maven 項目

idea 新建一個項目&#xff1a; 來到 New Project 頁面&#xff1a; 這里我們有兩種方式創建 maven 項目&#xff0c;一種是自定義創建&#xff0c;另一種是使用 maven 模版項目創建。 自定義創建 maven 項目 基本配置 Name: first_maven_project 項目名稱&#xff0c;設為 …

uni小程序中使用Echarts圖表

前言 今天雞米花給大家帶來的是在uni里面使用echarts&#xff0c;能夠完美支持和PC端一樣的效果&#xff0c;我這邊的工程是uni轉為微信小程序&#xff0c;用的是vue3vite來寫的&#xff0c;然后實現了豎屏和橫屏的展示方式&#xff0c;好了獻上效果圖。 效果圖 一、引入插件 這…

從FOTA測試到汽車電子安全體系的啟蒙之旅

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

stm32中 中斷和事件的區別

一、核心概念比喻想象一下工廠里的一個報警系統&#xff1a;?中斷 (Interrupt)??&#xff1a;就像火警警報器響了。它的目的是通知管理員&#xff08;CPU&#xff09;??&#xff1a;“著火了&#xff01;”。管理員聽到后&#xff0c;會停下手中的工作&#xff08;保存現場…

深入理解MySQL主從架構中的Seconds_Behind_Master指標

問題&#xff1a;主從延遲與寫后讀不一致 在典型的 MySQL 主從架構下&#xff0c;所有寫操作都會直接進入主庫&#xff0c;而讀操作大多分流到從庫&#xff0c;從而實現讀寫分離&#xff0c;緩解主庫壓力。 然而 MySQL 的復制機制是異步的&#xff1a;主庫先寫入 binlog&#…

MySQL安裝(linux版本)

MySQL安裝&#xff08;linux版本&#xff09; 課程地址 08. 進階-MySQL安裝(linux版本)_嗶哩嗶哩_bilibili 安裝過程中所有需要的程序都放在網盤里了 通過網盤分享的文件&#xff1a;虛擬機 鏈接: https://pan.baidu.com/s/1eLMD2iq1uEujNN7mWs2dIg?pwdckmh 提取碼: ckmh …