TCP/UDP/IP协议介绍

发布时间:2026/8/31 5:41:09
TCP/UDP/IP协议介绍 TCP/IP协议介绍TCP/IP协议包含的范围非常的广它是一种四层协议包含了各种硬件、软件需求的定义。TCP/IP协议确切的说法应该是TCP/UDP/IP协议。UDP协议(User Datagram Protocol 用户数据报协议)是一种保护消息边界的不保障可靠数据的传输。TCP协议(Transmission Control Protocol 传输控制协议)是一种流传输的协议。他提供可靠的、有序的、双向的、面向连接的传输。保护消息边界就是指传输协议把数据当作一条独立的消息在网上传输接收端只能接收独立的消息。也就是说存在保护消息边界接收端一次只能接收发送端发出的一个数据包。而面向流则是指无保护消息边界的如果发送端连续发送数据接收端有可能在一次接收动作中会接收两个或者更多的数据包。举例来说假如我们连续发送三个数据包大小分别是2k、4k、8k这三个数据包都已经到达了接收端的网络堆栈中如果使用UDP协议不管我们使用多大的接收缓冲区去接收数据我们必须有三次接收动作才能够把所有的数据包接收完。而使用TCP协议我们只要把接收的缓冲区大小设置在14k以上我们就能够一次把所有的数据包接收下来只需要有一次接收动作。这就是因为UDP协议的保护消息边界使得每一个消息都是独立的。而流传输却把数据当作一串数据流它不认为数据是一个一个的消息。所以有很多人在使用TCP协议通讯的时候并不清楚TCP是基于流的传输当连续发送数据的时候他们时常会认为TCP会丢包。其实不然因为当它们使用的缓冲区足够大时它们有可能会一次接收到两个甚至更多的数据包而很多人往往会忽视这一点只解析检查了第一个数据包而已经接收的其它据包却被忽略了。TCP 与 UDP 协议对比TCP 和 UDP 是传输层的两大核心协议二者在连接方式、可靠性、传输方式等方面存在明显差异。下面通过一个表格进行直观对比对比维度TCPUDP连接性面向连接需先建立连接三次握手无连接无需建立连接即可发送数据可靠性可靠传输提供确认、重传、排序机制不可靠传输不保证数据一定到达传输方式面向字节流无消息边界面向数据报保护消息边界消息边界无保护消息边界接收端可能一次收到多个数据包有保护消息边界一次接收一个完整数据报速度相对较慢因需建立连接和确认机制相对较快开销小、延迟低应用场景文件传输、网页浏览、邮件收发等对可靠性要求高的场景视频直播、语音通话、在线游戏等对实时性要求高的场景简单来说TCP 更注重数据的完整性和可靠性适合对数据准确性要求较高的场景而 UDP 更注重传输速度和实时性适合对延迟敏感、允许少量丢包的场景。实际开发中应根据业务需求在二者之间做出合理选择。一、先搞懂几个基本概念网络编程用大白话说就是写程序让两台联网的计算机互相交换数据。Socket套接字就是计算机之间进行通信的一种约定和技术。入门前提是要有一点 C 语言基础和基础的 TCP/IP 知识。建议先了解这几个名词TCP/IP网络通信的核心协议包含 TCP传输和 IP寻址两个协议三次握手TCP 建立连接的过程IP 地址和端口号一台机器上可能有多个程序靠IP 找机器 端口找程序来定位二、掌握核心 API 调用流程Linux 下用 C 做 TCP 编程要调用socket、netinet等库函数。核心流程分服务端和客户端两条线重点服务器端Server流程socket()—— 创建套接字bind()—— 绑定 IP 和端口listen()—— 开始监听端口accept()—— 接受客户端连接read()/write()或recv()/send()—— 收发数据close()—— 关闭连接客服端Client流程socket()—— 创建套接字connect()—— 连接服务器read()/write()—— 收发数据close()—— 关闭连接注意数据收发函数Linux和windows下不同同时这两个组函数也有细微区别。具体细致情况可以借助ai查阅其他网站。可以参考这个网站 socket数据的发送和接收_C语言中文网三、完整代码示例下面给出一个完整的 C 语言 TCP 通信示例包含服务端和客户端两部分。代码在 Linux 环境下编译运行使用gcc编译即可。3.1 服务端代码server.c#include stdio.h #include stdlib.h #include string.h #include unistd.h #include arpa/inet.h #include sys/socket.h #define PORT 8888 #define BUFFER_SIZE 1024 int main() { int server_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len sizeof(client_addr); char buffer[BUFFER_SIZE] {0}; // 1. 创建套接字 server_fd socket(AF_INET, SOCK_STREAM, 0); if (server_fd lt; 0) { perror(socket); exit(EXIT_FAILURE); } // 2. 绑定 IP 和端口 memset(amp;server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_addr.s_addr htonl(INADDR_ANY); server_addr.sin_port htons(PORT); if (bind(server_fd, (struct sockaddr *)amp;server_addr, sizeof(server_addr)) lt; 0) { perror(bind); close(server_fd); exit(EXIT_FAILURE); } // 3. 开始监听端口 if (listen(server_fd, 5) lt; 0) { perror(listen); close(server_fd); exit(EXIT_FAILURE); } printf(Server listening on port %d...\n, PORT); // 4. 接受客户端连接 client_fd accept(server_fd, (struct sockaddr *)amp;client_addr, amp;client_len); if (client_fd lt; 0) { perror(accept); close(server_fd); exit(EXIT_FAILURE); } printf(Client connected: %s:%d\n, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); // 5. 收发数据 read(client_fd, buffer, BUFFER_SIZE); printf(Received from client: %s\n, buffer); const char *response Hello from server!; write(client_fd, response, strlen(response)); // 6. 关闭连接 close(client_fd); close(server_fd); return 0; }3.2 客户端代码client.c#include stdio.h #include stdlib.h #include string.h #include unistd.h #include arpa/inet.h #include sys/socket.h #define PORT 8888 #define BUFFER_SIZE 1024 int main() { int client_fd; struct sockaddr_in server_addr; char buffer[BUFFER_SIZE] {0}; // 1. 创建套接字 client_fd socket(AF_INET, SOCK_STREAM, 0); if (client_fd lt; 0) { perror(socket); exit(EXIT_FAILURE); } // 2. 连接服务器 memset(amp;server_addr, 0, sizeof(server_addr)); server_addr.sin_family AF_INET; server_addr.sin_port htons(PORT); if (inet_pton(AF_INET, 127.0.0.1, amp;server_addr.sin_addr) lt; 0) { perror(inet_pton); close(client_fd); exit(EXIT_FAILURE); } if (connect(client_fd, (struct sockaddr *)amp;server_addr, sizeof(server_addr)) lt; 0) { perror(connect); close(client_fd); exit(EXIT_FAILURE); } printf(Connected to server...\n); // 3. 收发数据 const char *message Hello from client!; write(client_fd, message, strlen(message)); read(client_fd, buffer, BUFFER_SIZE); printf(Received from server: %s\n, buffer); // 4. 关闭连接 close(client_fd); return 0; }3.3 编译与运行结果分别编译服务端和客户端gcc server.c -o server gcc client.c -o client先在一个终端启动服务端再在另一个终端启动客户端./server ./client运行结果如下# 服务端输出 Server listening on port 8888... Client connected: 127.0.0.1:52341 Received from client: Hello from client! 客户端输出 Connected to server... Received from server: Hello from server!可以看到客户端发送的Hello from client!被服务端成功接收并打印服务端回复的Hello from server!也被客户端接收。整个流程对应了前面介绍的socket()、bind()、listen()、accept()、connect()、read()/write()、close()等核心 API 调用顺序。