创建套接字并bind的详细过程

bind()套接字编程 中的一个关键函数,用于 将套接字(socket)与特定的 IP 地址和端口号绑定 。它通常用于 服务器端,但也可以用于客户端(如指定本地端口)。


1. bind() 的作用

  • 服务器端:绑定一个固定的 IP 和端口,以便客户端可以连接。

  • 客户端(可选):可以绑定特定的本地端口(如某些协议要求固定端口)。

关键点:

  • TCP/UDP 服务器必须调用 bind(),否则客户端无法连接。

  • 客户端通常不需要 bind(),系统会自动分配临时端口。


2. bind() 的函数原型

cpp 复制代码
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

参数 说明
sockfd 套接字文件描述符(由 socket() 创建)
addr 指向 struct sockaddr 的指针,包含 IP 和端口
addrlen addr 结构体的大小(sizeof(struct sockaddr_in)

返回值:

  • 成功 :返回 0

  • 失败 :返回 -1,并设置 errno(如 EADDRINUSE 表示端口被占用)


3. bind() 的使用步骤

(1) 创建套接字
cpp 复制代码
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP
// 或
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  // UDP
(2) 设置地址结构(struct sockaddr_in
cpp 复制代码
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); // 清空结构体
addr.sin_family = AF_INET;       // IPv4
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡(0.0.0.0)
addr.sin_port = htons(8080);     // 绑定端口 8080

关键字段说明:

字段 说明
sin_family 地址族(AF_INET 表示 IPv4)
sin_addr.s_addr IP 地址(INADDR_ANY 表示监听所有网卡)
sin_port 端口号(必须用 htons() 转换字节序)
(3) 调用 bind()
cpp 复制代码
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    perror("bind failed");
    exit(1);
}

4. bind() 的常见问题

(1) 端口被占用(EADDRINUSE
  • 原因:另一个进程已经绑定了该端口。

  • 解决方法

    • 换一个端口。

    • 使用 SO_REUSEADDR 选项允许端口复用:

      cpp 复制代码
      int opt = 1;
      setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
(2) 权限不足(EACCES
  • 原因 :绑定 1024 以下的端口 (如 80、443)需要 root 权限。

  • 解决方法

    • sudo 运行程序。

    • 改用 1024 以上的端口(如 8080)。

(3) 绑定失败(EINVAL
  • 原因 :套接字已经绑定过,或者 addr 结构体不正确。

  • 解决方法:检查代码逻辑。


5. bind() 在 TCP/UDP 中的区别

TCP UDP
是否需要 bind() 服务器必须,客户端可选 服务器必须,客户端可选
典型用途 让客户端能 connect() 让客户端能 sendto()
绑定后操作 listen() + accept() 直接 recvfrom()/sendto()

6. 完整示例(TCP 服务器)

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

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

    // 2. 设置地址结构
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
    addr.sin_port = htons(8080); // 绑定 8080 端口

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

    printf("Server is running on port 8080...\n");
    close(sockfd);
    return 0;
}

总结

  • bind() 的作用 :将套接字绑定到 IP + 端口

  • 服务器必须 bind(),客户端通常不需要。

  • 常见错误

    • EADDRINUSE(端口被占用)→ 使用 SO_REUSEADDR

    • EACCES(权限不足)→ 改用高端口或 sudo

  • TCP vs UDPbind() 的用法基本相同,但后续操作不同(listen() vs recvfrom())。

相关推荐
换个昵称都难16 分钟前
webrtc 音频模块FEC模块
网络·音视频·webrtc
youngerwang43 分钟前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
智慧光迅AINOPOL3 小时前
校园在线巡课系统方案:督导全覆盖
网络·全光网解决方案·全光网·校园全光网·校园全光网解决方案
酉鬼女又兒4 小时前
零基础入门计算机网络:网络层核心任务、三大关键问题、两种服务类型与 TCP/IP 网际层协议体系全解析
服务器·网络·网络协议·tcp/ip·计算机网络·php·求职招聘
Urbano4 小时前
工装制作全流程科普:从面料到自动化生产
网络·人工智能
2401_868534784 小时前
网规笔记 | 真题解析:2018年11月软考网规-网络安全案例分析
网络
Gauss松鼠会4 小时前
【GaussDB】GaussDB重要通信参数汇总
服务器·网络·数据库·sql·性能优化·gaussdb·经验总结
超级无敌zhq5 小时前
后渗透痕迹清理:攻防对抗中的隐身术
网络·数据库·网络安全
“初生”5 小时前
Codex 桌面端新会话 5 次 Reconnecting 怎么办?HTTP/SSE 完美修复方案(2026最新)
网络·网络协议·http
m0_738120725 小时前
Docker 环境下 Vulfocus 靶场搭建全流程(附镜像源问题解决方案)
运维·服务器·网络·安全·docker·容器