当前位置: 首页 > article >正文

Linux TCP/UDP 网络编程完全指南:从基础到实践

引言在 Linux 网络编程中传输层提供两种核心协议TCP传输控制协议和UDP用户数据报协议。它们各有特点适用于不同的应用场景。特性TCPUDP连接性面向连接三次握手无连接可靠性可靠确认重传不可靠尽最大努力数据边界流式服务无边界数据报服务有边界传输效率较低较高适用场景文件传输、网页访问实时音视频、DNS查询今天我们将深入学习 TCP 和 UDP 的编程模型理解它们的核心差异并通过完整的代码示例掌握两种协议的使用方法。第一部分TCP 编程回顾一、TCP 服务端完整代码#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #define PORT 6000 #define BUFFER_SIZE 128 int main() { int listen_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len; char buffer[BUFFER_SIZE]; // 1. 创建套接字 listen_fd socket(AF_INET, SOCK_STREAM, 0); if (listen_fd -1) { perror(socket error); exit(1); } // 2. 绑定 IP 和端口 memset(server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_port htons(PORT); server_addr.sin_addr.s_addr htonl(INADDR_ANY); if (bind(listen_fd, (struct sockaddr*)server_addr, sizeof(server_addr)) -1) { perror(bind error); exit(1); } // 3. 创建监听队列 if (listen(listen_fd, 5) -1) { perror(listen error); exit(1); } printf(TCP 服务器启动成功端口%d\n, PORT); while (1) { // 4. 接受客户端连接 client_len sizeof(client_addr); client_fd accept(listen_fd, (struct sockaddr*)client_addr, client_len); if (client_fd -1) { perror(accept error); continue; } printf(客户端连接%s:%d\n, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); // 5. 循环接收数据 while (1) { memset(buffer, 0, BUFFER_SIZE); int n recv(client_fd, buffer, BUFFER_SIZE - 1, 0); if (n 0) { printf(客户端已断开\n); break; } if (n -1) { perror(recv error); break; } printf(收到数据%s\n, buffer); send(client_fd, OK, 2, 0); } close(client_fd); } close(listen_fd); return 0; }二、TCP 客户端完整代码#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #define PORT 6000 #define BUFFER_SIZE 128 int main() { int sock_fd; struct sockaddr_in server_addr; char buffer[BUFFER_SIZE]; // 1. 创建套接字 sock_fd socket(AF_INET, SOCK_STREAM, 0); if (sock_fd -1) { perror(socket error); exit(1); } // 2. 设置服务器地址 memset(server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_port htons(PORT); server_addr.sin_addr.s_addr inet_addr(127.0.0.1); // 3. 连接服务器 if (connect(sock_fd, (struct sockaddr*)server_addr, sizeof(server_addr)) -1) { perror(connect error); exit(1); } printf(连接服务器成功\n); // 4. 循环收发数据 while (1) { printf(请输入消息输入end退出); fgets(buffer, BUFFER_SIZE, stdin); buffer[strlen(buffer) - 1] \0; if (strcmp(buffer, end) 0) { break; } send(sock_fd, buffer, strlen(buffer), 0); memset(buffer, 0, BUFFER_SIZE); recv(sock_fd, buffer, BUFFER_SIZE - 1, 0); printf(服务器响应%s\n, buffer); } close(sock_fd); return 0; }三、netstat 命令使用# 查看所有 TCP 连接netstat -natp# 查看特定端口netstat -natp | grep 6000# 查看 UDP 服务netstat -nauptnetstat 输出字段说明字段含义Proto协议类型TCP/UDPRecv-Q接收缓冲区待处理数据量Send-Q发送缓冲区待处理数据量Local Address本地 IP:端口Foreign Address对端 IP:端口State连接状态TCPPID/Program name进程ID/程序名第二部分TCP 协议栈深入理解一、监听套接字与连接套接字套接字类型功能生命周期监听套接字接收客户端连接请求整个服务周期连接套接字与特定客户端通信单次会话周期二、TCP 缓冲区机制TCP 是流式服务数据在发送方和接收方都有缓冲区重要特性send()成功只表示数据已写入发送缓冲区不代表对方已接收recv()从接收缓冲区读取数据缓冲区为空时阻塞TCP 允许分次读取如recv1字节可逐个接收// 实验修改接收长度为1字节观察现象 // 客户端发送 hello 需要5次 recv 才能读完 int n recv(client_fd, buffer, 1, 0); // 每次只读1字节三、TCP vs UDP 数据接收对比场景TCPUDP发送端多次 send 可能合并每次 sendto 独立报文接收端可分批读取必须单次完整读取数据边界无边界流有边界数据报第三部分UDP 编程一、UDP 服务端完整代码UDP 无需建立连接使用recvfrom()和sendto()收发数据。#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #define PORT 6000 #define BUFFER_SIZE 128 int main() { int sock_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len; char buffer[BUFFER_SIZE]; // 1. 创建套接字注意SOCK_DGRAM sock_fd socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd -1) { perror(socket error); exit(1); } // 2. 绑定 IP 和端口 memset(server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_port htons(PORT); server_addr.sin_addr.s_addr htonl(INADDR_ANY); if (bind(sock_fd, (struct sockaddr*)server_addr, sizeof(server_addr)) -1) { perror(bind error); exit(1); } printf(UDP 服务器启动成功端口%d\n, PORT); while (1) { client_len sizeof(client_addr); memset(buffer, 0, BUFFER_SIZE); // 3. 接收数据同时获取客户端地址 int n recvfrom(sock_fd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr*)client_addr, client_len); if (n -1) { perror(recvfrom error); continue; } printf(收到来自 %s:%d 的数据%s\n, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buffer); // 4. 回复数据需要指定客户端地址 sendto(sock_fd, OK, 2, 0, (struct sockaddr*)client_addr, client_len); } close(sock_fd); return 0; }二、UDP 客户端完整代码#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #define PORT 6000 #define BUFFER_SIZE 128 int main() { int sock_fd; struct sockaddr_in server_addr; socklen_t server_len; char buffer[BUFFER_SIZE]; // 1. 创建套接字 sock_fd socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd -1) { perror(socket error); exit(1); } // 2. 设置服务器地址 memset(server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_port htons(PORT); server_addr.sin_addr.s_addr inet_addr(127.0.0.1); server_len sizeof(server_addr); while (1) { printf(请输入消息输入end退出); fgets(buffer, BUFFER_SIZE, stdin); buffer[strlen(buffer) - 1] \0; if (strcmp(buffer, end) 0) { break; } // 3. 发送数据需指定目标地址 sendto(sock_fd, buffer, strlen(buffer), 0, (struct sockaddr*)server_addr, server_len); memset(buffer, 0, BUFFER_SIZE); // 4. 接收回复 recvfrom(sock_fd, buffer, BUFFER_SIZE - 1, 0, NULL, NULL); printf(服务器响应%s\n, buffer); } close(sock_fd); return 0; }三、UDP 核心函数详解recvfrom 函数ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);参数说明sockfd套接字描述符buf接收数据缓冲区len缓冲区大小flags标志位通常为0src_addr输出参数存储发送方地址addrlen输入输出参数地址结构大小sendto 函数ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);参数说明sockfd套接字描述符buf发送数据缓冲区len数据长度flags标志位通常为0dest_addr目标地址addrlen地址结构大小第四部分TCP vs UDP 核心差异一、协议特性对比特性TCPUDP连接性面向连接三次握手无连接可靠性确认重传、顺序保证尽最大努力可能丢包数据边界流式无边界数据报有边界拥塞控制有无传输效率较低较高编程复杂度较高较低二、编程模型对比操作TCPUDP创建套接字socket(AF_INET, SOCK_STREAM, 0)socket(AF_INET, SOCK_DGRAM, 0)绑定地址bind()bind()建立连接服务端listen()accept()不需要建立连接客户端connect()不需要发送数据send()/write()sendto()接收数据recv()/read()recvfrom()获取对端地址accept()返回recvfrom()返回三、数据接收特性对比TCP 流式服务// 发送端多次 send send(fd, hello, 5, 0); send(fd, world, 5, 0); // 接收端可能一次收到 helloworld也可能分次收到 // 数据没有边界UDP 数据报服务// 发送端每次 sendto 独立 sendto(fd, hello, 5, 0, ...); sendto(fd, world, 5, 0, ...); // 接收端每次 recvfrom 对应一次 sendto // 数据有边界必须单次完整读取 // 如果缓冲区太小剩余数据会被丢弃第五部分端口复用与并发一、端口复用规则场景是否可复用说明TCP TCP 同一端口❌ 不可端口已被占用UDP UDP 同一端口❌ 不可端口已被占用TCP UDP 同一端口✅ 可不同协议互不冲突# 验证TCP 6000 和 UDP 6000 可同时存在netstat -naupt | grep 6000二、UDP 的并发特性UDP 是无连接的单线程即可处理多个客户端总结一、TCP vs UDP 速查表对比项TCPUDP套接字类型SOCK_STREAMSOCK_DGRAM服务端流程socket→bind→listen→accept→recv/send→closesocket→bind→recvfrom→sendto→close客户端流程socket→connect→send/recv→closesocket→sendto→recvfrom→close数据边界无流有数据报并发实现需要多进程/多线程单线程即可二、代码运行测试# 编译 UDP 程序gcc udp_server.c -o udp_servergcc udp_client.c -o udp_client# 先启动服务器./udp_server# 另一终端启动客户端可多个./udp_client三、面试高频考点TCP 三次握手SYN → SYNACK → ACKTCP 四次挥手FIN → ACK → FIN → ACKTCP vs UDP 区别连接性、可靠性、数据边界端口复用不同协议可绑定同一端口UDP 数据报边界必须单次完整读取本文详细介绍了 TCP 和 UDP 网络编程包括TCP 服务端/客户端完整实现理解面向连接的通信模型UDP 服务端/客户端完整实现理解数据报服务的特点核心差异分析连接性、可靠性、数据边界端口复用与并发UDP 天然支持多客户端课后任务整理 TCP 和 UDP 的对比笔记动手运行两种协议的代码观察 UDP 数据报截断现象减小 recvfrom 缓冲区

相关文章:

Linux TCP/UDP 网络编程完全指南:从基础到实践

引言在 Linux 网络编程中,传输层提供两种核心协议:TCP(传输控制协议) 和 UDP(用户数据报协议)。它们各有特点,适用于不同的应用场景。特性TCPUDP连接性面向连接(三次握手&#xff09…...

多模态模型数据筛选:提升AI性能的关键策略

1. 多模态推理模型的数据筛选困境去年我在参与一个医疗影像与文本报告的联合分析项目时,团队花了大半年时间收集了超过200万条数据样本。但当我们把这些数据直接喂给多模态模型后,效果却出人意料地差——模型在测试集上的准确率比单模态模型还低了12%。经…...

SpaceMolt Client:基于Bun的CLI工具,实现游戏API自动化与AI智能体集成

1. 项目概述与核心价值 如果你是一名开发者,尤其是对AI智能体、自动化脚本或者命令行工具感兴趣,那么你很可能已经厌倦了那些需要反复点击网页、在浏览器和代码编辑器之间来回切换的在线游戏体验。SpaceMolt Client的出现,正是为了解决这个问…...

语音识别鲁棒性评估:混响环境下的ASR性能优化

1. 项目背景与核心价值在语音识别技术快速发展的今天,我们常常忽略了一个关键问题:实际应用场景中的语音信号往往不是实验室里的"纯净样本"。会议室、客厅、走廊等真实环境产生的混响效应,会显著影响自动语音识别(ASR&a…...

Unity开发AI助手API幻觉终结方案:MCP协议与本地数据库实践

1. 项目概述:当AI助手遇上Unity开发,如何终结API幻觉? 如果你是一名Unity开发者,同时又在使用Claude、Cursor这类AI编程助手,那你一定经历过这样的场景:你问AI“Unity里怎么异步加载场景?”&…...

【R语言污染溯源建模实战指南】:20年环境数据科学家亲授3大不可绕过的建模陷阱与5步标准化流程

更多请点击: https://intelliparadigm.com 第一章:R语言污染溯源建模的科学逻辑与环境意义 污染溯源建模是环境风险评估与精准治理的核心环节,其科学逻辑建立在“源—路径—受体”三维因果链之上。R语言凭借其强大的统计建模能力、丰富的空间…...

PHP表单引擎兼容性灾难现场:PHP 8.3+ JIT、Swoole 5.1协程、RoadRunner v2024——跨运行时适配避坑清单

更多请点击: https://intelliparadigm.com 第一章:PHP表单引擎的核心架构与设计哲学 PHP表单引擎并非简单地封装HTML标签,而是以“声明式定义 运行时编排”为设计内核,将表单视为可组合、可验证、可序列化的领域对象。其核心由三…...

FreeRTOS heap4内存管理源码逐行解读:从链表操作到内存碎片合并的实战指南

FreeRTOS heap4内存管理源码深度剖析:从链表设计到碎片优化的工程实践 在嵌入式系统开发中,内存管理往往是最考验工程师功底的领域之一。FreeRTOS作为业界领先的实时操作系统,其heap4内存管理器以简洁高效的设计,成为许多关键系统…...

如何在Windows 11上完美运行安卓应用:WSA完整使用指南

如何在Windows 11上完美运行安卓应用:WSA完整使用指南 【免费下载链接】WSA Developer-related issues and feature requests for Windows Subsystem for Android 项目地址: https://gitcode.com/gh_mirrors/ws/WSA 你是否想过在Windows电脑上流畅运行手机应…...

环境配置与基础教程:实战踩坑:多进程 DataLoader 中 num_workers 与 pin_memory 的底层逻辑与性能调优最佳实践

前言:那个让 GPU “假忙” 的隐形杀手 如果你曾盯着 nvidia-smi 上那个 90%+ 的 GPU 利用率数字暗自放心,那你很可能已经被 “利用率幻觉” 欺骗了很久。 根据 Unite.ai 联合 Ingero 开源团队在 2026 年 3 月发布的一项内核级跟踪调查,PyTorch DataLoader 在纯内存 GPU 工…...

ncmdump实践指南:如何快速解密网易云音乐NCM格式音频文件

ncmdump实践指南:如何快速解密网易云音乐NCM格式音频文件 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 在数字音乐时代,格式兼容性成为用户面临的实际问题。网易云音乐采用的NCM加密格式虽然保护了版权&…...

ABAP-OO:(7)类对象的动态创建和调用

在 ABAP 面向对象开发中,动态创建数据、动态创建对象、动态调用方法是实现灵活架构、低耦合、可配置化的关键技术。它区别于静态编码,核心特点是:类型与行为不在编译期固定,而是在程序运行时动态决定。 一、什么是动态创建&#x…...

Kagantic-Codebase:AI协作代码库治理框架的设计与实践

1. 项目概述:为AI协作而生的代码库治理框架如果你正在尝试将AI助手(比如Claude Code、Cursor、GitHub Copilot)深度集成到你的开发工作流中,并且已经受够了每次都要在聊天框里重复解释项目结构、编码规范和操作边界的麻烦&#xf…...

强化学习在医学视觉语言模型中的应用与优化

1. 项目概述作为一名长期从事医学AI研究的从业者,我见证了强化学习(RL)在医学视觉语言模型领域的崛起。这个交叉领域正在重塑医学影像分析的范式——从传统的单一图像识别,进化到能够理解影像内容并生成专业诊断描述的智能系统。在…...

AI记忆系统演进:从废弃三层架构到实时向量存储实践

1. 项目概述:从废弃的蓝图到现代AI记忆系统的演进如果你正在为你的AI助手寻找一个持久、可搜索的记忆系统,并且偶然发现了openclaw-jarvis-memory这个项目,那么你可能会看到它已经被标记为“废弃”。别急着关掉页面,这恰恰是一个绝…...

智能家居改造第一步:如何安全地为智能开关接入零线?老房无零线解决方案盘点

智能家居改造第一步:如何安全地为智能开关接入零线?老房无零线解决方案盘点 智能家居的普及让传统开关逐渐被智能开关取代,但许多用户在改造过程中遇到一个棘手问题:老房子的开关底盒里可能没有零线。这种情况在2000年以前建造的住…...

利用快马平台与hyperdown快速构建markdown实时预览编辑器原型

最近在做一个需要快速验证想法的项目时,发现用InsCode(快马)平台配合hyperdown解析器来搭建markdown实时预览编辑器特别方便。整个过程从构思到实现只用了不到半小时,完全不需要操心环境配置的问题,特别适合需要快速原型验证的场景。 为什么…...

文明越复杂,伪装就越精致,人性就越容易迷失在符号之中

你说得非常透彻,而且带着一种历史穿透力的清醒。“看最原始的东西就行了”——这其实是一种政治经济学的底层思维:剥开制度、话语、技术、法律的外衣,直视权力与资源分配的本质。一、你说的“原始的东西”是什么?其实就是人类组织…...

AI命令行代理评测框架Terminal-Bench设计与实践

1. 项目背景与核心价值命令行终端是开发者日常工作中不可或缺的效率工具。随着AI技术的快速发展,各类AI代理开始尝试理解并执行自然语言指令来自动化终端操作。但如何量化评估这些AI代理在真实命令行环境中的表现,一直缺乏系统化的评测方案。这正是Termi…...

别再纠结选哪个了!51单片机AD转换方案全对比:XPT2046、PCF8591和内部ADC到底怎么选?

51单片机AD转换方案深度评测:XPT2046、PCF8591与内部ADC实战指南 在嵌入式系统开发中,模拟信号采集是连接物理世界与数字系统的关键桥梁。面对市面上琳琅满目的AD转换方案,工程师们常常陷入选择困境:是使用外置专业芯片还是依赖单…...

Reactor:基于节点化工作流的AI人脸修复与替换引擎深度解析

1. 项目概述:一个被低估的AI图像生成工作流引擎如果你最近在折腾Stable Diffusion,大概率听说过ComfyUI。它以节点式的工作流和强大的自定义能力,成为了许多高阶玩家的首选。但今天我想聊的,是另一个同样基于节点、但在设计理念和…...

选型指南:TJA1021、MC33662等主流LIN收发器怎么选?从单通道到四通道全解析

LIN收发器选型实战指南:从单通道到四通道的工程决策 汽车电子工程师在设计LIN总线节点时,往往会在收发器选型环节陷入纠结。面对NXP、Infineon等厂商的数十种型号,如何根据项目需求精准匹配?我们以实际工程案例为线索,…...

别再让显存拖后腿了:手把手教你用VLLM的PageAttention优化大模型推理

突破大模型推理瓶颈:VLLM与PageAttention实战指南 当你在深夜调试一个即将上线的智能客服系统时,突然发现并发请求量稍大就会触发显存不足的警报——这种场景对AI开发者来说再熟悉不过。大语言模型推理过程中的显存管理问题,就像一道无形的天…...

2026年AI大模型接口中转站全网实测:五大头部服务商谁能脱颖而出,引领行业潮流?

【2026年3月31日 科技产业快讯】2026年,全球AI大模型产业正式从技术创新阶段步入规模化商业落地阶段。AI大模型接口中转站作为连接底层模型能力和上层产业应用的关键基础设施,其市场需求呈现出指数级的增长。国家数据局最新公布的数据显示,截…...

初识AI产品经理:我的学习心得与“夸父追日“感悟(收藏版)

本文以作者成为AI产品经理第一个月的真实学习体验切入,用"夸父追日"比喻AI领域知识更新速度远超学习速度的现实。文章核心聚焦AI产品经理与传统PM的思维差异(管确定性 vs 不确定性)、必备基础能力(需求分析、沟通、PRD写…...

零售业RFID技术实施指南:从合规到高效供应链

1. 零售业RFID合规实施全景解读2003年沃尔玛首次在零售行业推行托盘和箱级RFID标签计划时,这项技术还被视为供应链管理的"未来选项"。如今走过二十年发展历程,RFID技术已从最初的合规要求演变为提升供应链效率的核心工具。作为参与过多个跨国零…...

深入DSP F28335 ADC内核:用示波器实测同步采样与顺序采样的时序差异(附代码与波形图)

深入解析DSP F28335 ADC内核:同步与顺序采样的硬件实测与时序优化 在嵌入式系统开发中,ADC(模数转换器)的性能往往直接决定了整个系统的精度上限。德州仪器(TI)的F28335数字信号处理器搭载的12位ADC模块&am…...

别再空谈概念了!用Python+Three.js从零搭建一个简易的智慧城市数字孪生原型

用PythonThree.js从零构建智慧城市数字孪生原型:十字路口交通模拟实战 当技术博客充斥着数字孪生的概念解析时,真正能让开发者兴奋的永远是动手实现的快感。想象一下,你不仅能理解红绿灯调度算法,还能在三维空间中实时观察车流如何…...

VA-π混合架构:像素级图像生成的策略对齐技术

1. 项目概述:当像素遇上策略对齐 在图像生成领域,我们常常面临一个核心矛盾:如何让生成模型既保持像素级的精细控制,又能理解高层次的语义策略?VA-π(Variational Policy-Aligned Pixelwise Autoregression…...

CSS动画与变换的结合应用

在前端开发中,CSS动画和变换(Transform)是实现视觉效果的两个重要工具。通过合理地结合这两个特性,可以创造出流畅且吸引人的用户界面。本文将通过一个具体实例,探讨如何在CSS中同时使用transform和animation属性来实现一个元素的进入动画和悬停放大效果。 背景介绍 假设…...