TCP 和 UDP 在创建套接字(Socket)时的区别

发布于:2025-07-20 ⋅ 阅读:(14) ⋅ 点赞:(0)

1. 创建套接字的区别

(1) TCP 套接字(SOCK_STREAM)

  • 面向连接,必须先建立连接(connect()/accept())才能通信。

  • 可靠传输,保证数据顺序、不丢失、不重复。

  • 适用于需要稳定传输的场景(如 HTTP、FTP、SSH)。

TCP 套接字创建流程
#include <sys/socket.h>

// 1. 创建 TCP 套接字(SOCK_STREAM)
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
    perror("socket() failed");
    exit(1);
}

// 2. 绑定地址(可选,服务器通常需要 bind())
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有 IP
addr.sin_port = htons(8080);              // 端口 8080

if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    perror("bind() failed");
    exit(1);
}

// 3. 监听连接(仅服务器需要)
if (listen(sockfd, 5) < 0) {  // 5 是等待队列长度
    perror("listen() failed");
    exit(1);
}

// 4. 接受连接(服务器)或发起连接(客户端)
// 服务器端:
int client_fd = accept(sockfd, NULL, NULL);
// 客户端:
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));

(2) UDP 套接字(SOCK_DGRAM)

  • 无连接,直接发送数据,无需 connect()(但可以调用 connect() 绑定默认目标)。

  • 不可靠传输,数据可能丢失、乱序、重复。

  • 适用于实时性要求高、允许少量丢包的场景(如 DNS、视频流、游戏)。

UDP 套接字创建流程
#include <sys/socket.h>

// 1. 创建 UDP 套接字(SOCK_DGRAM)
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
    perror("socket() failed");
    exit(1);
}

// 2. 绑定地址(可选,服务器通常需要 bind())
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有 IP
addr.sin_port = htons(8080);              // 端口 8080

if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    perror("bind() failed");
    exit(1);
}

// 3. 直接发送/接收数据(无需 listen/accept/connect)
// 发送数据:
sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
// 接收数据:
recvfrom(sockfd, buffer, buffer_len, 0, NULL, NULL);  // 不关心来源地址时

2. 核心区别对比

特性 TCP(SOCK_STREAM UDP(SOCK_DGRAM
连接方式 面向连接(connect()/accept() 无连接(直接 sendto()/recvfrom()
可靠性 可靠(不丢包、不重复、按序) 不可靠(可能丢包、乱序)
流量控制 有(滑动窗口) 无(直接发送)
传输效率 较低(有握手、确认机制) 较高(无额外控制)
适用场景 HTTP、FTP、SSH、数据库 DNS、视频流、VoIP、游戏
函数调用 socket() + bind() + listen() + accept() + connect() socket() + bind() + sendto()/recvfrom()

3. 如何选择 TCP 还是 UDP?

  • 用 TCP 的情况

    • 需要可靠传输(如文件下载、网页访问)。

    • 数据顺序必须保证(如数据库查询)。

    • 可以接受稍高的延迟(如 SSH 远程登录)。

  • 用 UDP 的情况

    • 实时性要求高(如视频会议、在线游戏)。

    • 允许少量丢包(如 VoIP 通话)。

    • 需要广播/组播(如 DHCP 获取 IP)。


4. 总结

TCP UDP
创建方式 socket(AF_INET, SOCK_STREAM, 0) socket(AF_INET, SOCK_DGRAM, 0)
是否需要 connect() 必须(客户端) 可选(可绑定默认目标)
是否需要 listen()/accept() 服务器必须 不需要
数据发送方式 send()/recv() 或 write()/read() sendto()/recvfrom()
典型应用 Web 服务器(HTTP)、SSH、MySQL DNS、视频流、QUIC(HTTP/3)

如果数据必须可靠到达,用 TCP;如果速度更重要,用 UDP。


网站公告

今日签到

点亮在社区的每一天
去签到