Linux 网络编程进阶:从 Socket基础到TCP/UDP 编程实战
1. 引言Linux 网络编程是后端开发、嵌入式开发和系统编程的核心技能之一。本文面向有一定 C 语言基础、希望系统掌握 Linux 网络编程的读者,从最基本的 socket 接口函数讲起,逐步深入到 TCP/UDP 服务端与客户端实战、UNIX 域协议、套接字选项以及广播与组播编程。全文以函数原型、参数说明、返回值分析和可运行示例为主线,帮助读者建立完整的网络编程知识体系。2. 基础函数Socket(套接字)是 Linux 网络编程的基石,它是对 TCP/IP 协议栈的封装,为应用程序提供了一套统一的网络通信接口。下面从最核心的 socket 函数开始讲解。2.1 socket 函数函数原型:#include sys/types.h #include sys/socket.h int socket(int domain, int type, int protocol);参数说明:domain:协议族,常用取值包括AF_INET(IPv4 网络协议)、AF_INET6(IPv6)、AF_UNIX(UNIX 域套接字)。type:套接字类型,常用取值包括SOCK_STREAM(流式套接字,面向连接,对应 TCP)、SOCK_DGRAM(数据报套接字,无连接,对应 UDP)、SOCK_RAW(原始套接字)。protocol:协议号,通常传 0 表示使用默认协议。也可以指定IPPROTO_TCP或IPPROTO_UDP。返回值:成功返回一个非负的文件描述符(套接字描述符);失败返回 -1,并设置 errno。示例:#include stdio.h #include sys/socket.h #include arpa/inet.h int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd 0) { perror("socket"); return 1; } printf("socket created, fd = %d\n", sockfd); return 0; }2.2 网络地址结构体在 Linux 网络编程中,地址结构体用于描述通信双方的地址信息。最常用的是 IPv4 地址结构体sockaddr_in,其定义如下:#include netinet/in.h struct sockaddr_in { sa_family_t sin_family; /* 地址族,AF_INET */ in_port_t sin_port; /* 端口号,网络字节序 */ struct in_addr sin_addr; /* IPv4 地址 */ char sin_zero[8]; /* 填充字段,保持与 sockaddr 大小一致 */ };其中struct in_addr的定义为:struct in_addr { in_addr_t s_addr; /* 32 位 IPv4 地址,网络字节序 */ };通用地址结构体sockaddr用于函数参数的统一类型:struct sockaddr { sa_family_t sa_family; /* 地址族 */ char sa_data[14]; /* 协议地址 */ };在实际编程中,通常先填充sockaddr_in,再强制转换为struct sockaddr *传入 bind、connect 等函数。2.3 IPv4 地址转换函数IPv4 地址在程序中通常以点分十进制字符串(如 "192.168.1.1")或 32 位二进制整数两种形式存在。地址转换函数用于在这两种形式之间转换。inet_pton 函数:将点分十进制字符串转换为网络字节序的二进制地址。#include arpa/inet.h int inet_pton(int af, const char *src, void *dst);af:地址族,通常为AF_INET。src:点分十进制字符串,如 "192.168.1.1"。dst:指向存放转换结果的struct in_addr的指针。返回值:成功返回 1;src 不是有效地址返回 0;af 不支持返回 -1。inet_ntop 函数:将网络字节序的二进制地址转换为点分十进制字符串。#include arpa/inet.h const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);af:地址族,通常为AF_INET。src:指向struct in_addr的指针。dst:存放转换结果的字符串缓冲区。size:缓冲区大小,IPv4 地址至少需要INET_ADDRSTRLEN(16 字节)。返回值:成功返回指向 dst 的指针;失败返回 NULL。示例:#include stdio.h #include arpa/inet.h int main() { struct in_addr addr; char buf[INET_ADDRSTRLEN]; // 字符串转二进制 if (inet_pton(AF_INET, "192.168.1.100", addr) != 1) { perror("inet_pton"); return 1; } // 二进制转字符串 if (inet_ntop(AF_INET, addr, buf, sizeof(buf)) == NULL) { perror("inet_ntop"); return 1; } printf("address: %s\n", buf); return 0; }inet_aton 函数:将点分十进制字符串转换为网络字节序的二进制地址,是早期常用的转换函数。#include arpa/inet.h int inet_aton(const char *cp, struct in_addr *inp);cp:点分十进制字符串,如 "192.168.1.1"。inp:指向存放转换结果的struct in_addr的指针。返回值:成功返回非 0;失败返回 0。inet_ntoa 函数:将网络字节序的二进制地址转换为点分十进制字符串,返回的字符串存放在静态缓冲区中。#include arpa/inet.h char *inet_ntoa(struct in_addr in);in:struct in_addr结构体,包含 32 位网络字节序地址。返回值:成功返回指向点分十进制字符串的指针;失败返回 NULL。注意该函数返回的字符串存放在静态缓冲区,多次调用会覆盖之前的结果。inet_addr 函数:将点分十进制字符串转换为网络字节序的 32 位二进制地址,已废弃,建议使用 inet_pton 替代。#include arpa/inet.h in_addr_t inet_addr(const char *cp);cp:点分十进制字符串,如 "192.168.1.1"。返回值:成功返回网络字节序的 32 位地址;失败返回INADDR_NONE(即 0xFFFFFFFF)。inet_network 函数:将点分十进制字符串转换为主机字节序的 32 位地址,不包含网络字节序转换。#include arpa/inet.h in_addr_t inet_network(const char *cp);cp:点分十进制字符串,如 "192.168.1.1"。返回值:成功返回主机字节序的 32 位地址;失败返回INADDR_NONE。示例:#include stdio.h #include arpa/inet.h int main() { struct in_addr addr; char buf[INET_ADDRSTRLEN]; // inet_aton:字符串转二进制 if (inet_aton("192.168.1.100", addr) == 0) { perror("inet_aton"); return 1; } printf("inet_aton: %s\n", inet_ntoa(addr)); // inet_ntoa:二进制转字符串 printf("inet_ntoa: %s\n", inet_ntoa(addr)); // inet_addr:字符串转网络字节序整数 in_addr_t net_addr = inet_addr("192.168.1.100"); if (net_addr == INADDR_NONE) { perror("inet_addr"); return 1; } printf("inet_addr: 0x%x\n", net_addr); // inet_network:字符串转主机字节序整数 in_addr_t host_addr = inet_network("192.168.1.100"); if (host_addr == INADDR_NONE) { perror("inet_network"); return 1; } printf("inet_network: 0x%x\n", host_addr); return 0; }2.4 网络字节序函数不同主机对多字节整数的存储方式不同(大端或小端),为保证网络通信的一致性,TCP/IP 协议规定使用大端字节序(网络字节序)。Linux 提供了一组字节序转换函数:#include arpa/inet.h uint32_t htonl(uint32_t hostlong); /* 主机字节序转网络字节序(32 位) */ uint16_t htons(uint16_t hostshort); /* 主机字节序转网络字节序(16 位) */ uint32_t ntohl(uint32_t netlong); /* 网络字节序转主机字节序(32 位) */ uint16_t ntohs(uint16_t netshort); /* 网络字节序转主机字节序(16 位) */参数说明:传入待转换的数值,返回转换后的数值。示例:#include stdio.h #include arpa/inet.h int main() { uint16_t port = 8080; uint16_t net_port = htons(port); printf("host port: %u, network port: %u\n", port, net_port); printf("back to host: %u\n", ntohs(net_port)); return 0; }3. 核心函数在 socket 创建完成后,服务端和客户端需要调用一系列函数建立连接并传输数据。本节详细讲解 bind、listen、accept、connect 四个核心函数。3.1 bind函数原型:#include sys/socket.h int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数说明:sockfd:socket 函数返回的套接字描述符。addr:指向地址结构体的指针,通常为struct sockaddr_in *强制转换而来。addrlen:地址结构体的大小,可用sizeof(struct sockaddr_in)。返回值:成功返回 0;失败返回 -1,并设置 errno。示例:#include stdio.h #include string.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd 0) { perror("socket"); return 1; } struct sockaddr_in server_addr; memset(server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 绑定所有本地地址 */ if (bind(sockfd, (struct sockaddr *)server_addr, sizeof(server_a

相关新闻

elasticsearch-js 基准测试指南:base64 编码 float32 向量的批量写入性能对比

elasticsearch-js 基准测试指南:base64 编码 float32 向量的批量写入性能对比

后端搜索引擎 【免费下载链接】elasticsearch-js Official Elasticsearch client library for Node.js 项目地址: https://gitcode.com/gh_mirrors/el/elasticsearch-js 点击查看 免费下载 本指南围绕 test/ingest/README.md 与其核心脚本 test/ingest/base64.mjs …

2026/10/13 3:10:46 阅读更多 →
从零搭建灌装监控系统(十八):自定义控件,三色灯与状态指示

从零搭建灌装监控系统(十八):自定义控件,三色灯与状态指示

自定义控件:三色灯与状态指示这是「从零搭建灌装监控系统」系列第18篇。界面上的红绿圆点、状态标签、液位指示,一开始都是复制粘贴出来的。这篇把它们做成可复用的自定义控件,用依赖属性和值转换器驱动,并讲清一个特别容易踩的 W…

2026/10/13 3:10:46 阅读更多 →
Linux 系统调试学习1

Linux 系统调试学习1

一个进程可以简单想成:Process │ ├── PID ├── 虚拟内存空间 ├── 文件描述符 ├── socket ├── 环境变量 ├── 当前工作目录 ├── 信号状态 └── 一个或多个线程所以以后你排查一个机器人节点时,其实是在看:这个进程 用了…

2026/10/13 3:10:46 阅读更多 →

最新新闻

darknet运行报错libopencv_highgui.so.3.2缺失?动态库排查与解决全攻略

darknet运行报错libopencv_highgui.so.3.2缺失?动态库排查与解决全攻略

直接跑./darknet就报错error while loading shared libraries: libopencv_highgui.so.3.2,这种动态库缺失的问题,估计每个搞深度学习目标检测的人都被它堵过一阵子。明明编译都过了,运行却翻车,查了半天也不知道到底哪里没对上。如…

2026/10/13 4:02:58 阅读更多 →
AnyPS5:面向PS5主机的本地化系统工具链设计与实现

AnyPS5:面向PS5主机的本地化系统工具链设计与实现

项目标题本身“AnyPS5”未提供足够上下文,但结合命名惯例、技术社区常见实践及合规安全边界,可明确判断:这是一个面向 PlayStation 5 主机的本地化工具类项目代号,聚焦于主机端系统级功能增强、本地环境适配或用户侧体验优化&…

2026/10/13 4:02:58 阅读更多 →
并查集动态维护连通块大小:‘星球联盟‘题解与易错点

并查集动态维护连通块大小:‘星球联盟‘题解与易错点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 4:02:58 阅读更多 →
AI原生IDE与插件深度对比:Cursor、Trae、通义灵码能力边界与选型指南

AI原生IDE与插件深度对比:Cursor、Trae、通义灵码能力边界与选型指南

这两年AI编程工具的变化速度,快得有点不讲道理。我回想最早用插件式AI补全的时候,代码行预测已经够惊艳了;但现在的AI原生IDE和新一代编程插件,已经把范围从“猜你下一个单词”扩展到了“替你改文件、跑命令、做收尾”。Cursor、T…

2026/10/13 4:02:58 阅读更多 →
GEO优化实战:让DeepSeek、Qwen、豆包、Kimi主动引用你的内容

GEO优化实战:让DeepSeek、Qwen、豆包、Kimi主动引用你的内容

上周我把同一个问题同时丢给 DeepSeek、Qwen、豆包、Kimi,问的是某工业软件厂商的产品优势。四个助手给出的答案里,只有两个提到了这个品牌,引用来源几乎没有交集;其中一个完整转述了官网页面上的一句话,另一个却把品牌…

2026/10/13 4:02:58 阅读更多 →
基于三菱PLC的自动配料控制系统设计:双速给料与落差补偿实战

基于三菱PLC的自动配料控制系统设计:双速给料与落差补偿实战

做自动配料控制系统,绕不开两件事:PLC的选型,和配料流程里那些让人头疼的细节——飞料、秤漂、配方切换、粘度变化导致的给料差异。这个“基于三菱PLC的自动配料控制系统的设计”项目,从需求拆解、硬件选型、控制逻辑到现场调试完…

2026/10/13 4:01:58 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →