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

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

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


1. bind() 的作用

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

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

关键点:

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

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


2. bind() 的函数原型

#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

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

返回值:

  • 成功:返回 0

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


3. bind() 的使用步骤

(1) 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP
// 或
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  // UDP
(2) 设置地址结构(struct sockaddr_in
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_addrIP 地址(INADDR_ANY 表示监听所有网卡)
sin_port端口号(必须用 htons() 转换字节序)
(3) 调用 bind()
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {perror("bind failed");exit(1);
}

4. bind() 的常见问题

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

  • 解决方法

    • 换一个端口。

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

      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 中的区别

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

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

#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.0addr.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())。

http://www.lryc.cn/news/593644.html

相关文章:

  • 深度学习-线性神经网络
  • 深度学习Depth Anything V2神经网络实现单目深度估计系统源码
  • 短视频矩阵的未来前景:机遇无限,挑战并存
  • Maven常用知识总结
  • 代码随想录算法训练营第二十天|回溯part02
  • 电阻耐压参数学习总结
  • 动态规划——数位DP经典题目
  • 【深度学习-Day 38】破解深度网络退化之谜:残差网络(ResNet)核心原理与实战
  • 从0到1搭建一个Rag引擎(ollama+Qwen3)
  • 实现el-select下拉框,下拉时加载数据
  • Docker容器原理和启动策略
  • EP01:【Python 第一弹】基础入门知识
  • aosp15实现SurfaceFlinger的dump输出带上Layer详细信息踩坑笔记
  • 生成式人工智能实战 | 自回归模型详解与实现
  • Linux中添加重定向(Redirection)功能到minishell
  • QGIS和QGC软件的区别
  • LVS部署模式NAT集群案例
  • buildroot运行qemu进行pcie设备模拟,开发驱动的方式
  • 【学习记录】智能客服小桃(进度更新ing)
  • 测试计划(抽奖系统)
  • Redis Sentinel哨兵集群
  • STC增强型单片机寄存器 PWM EEPROM TMOD TCON
  • ElasticSearch:商品SKU+SPU实现join查询,设计及优化
  • JavaScript 中的继承
  • ADC选型设计
  • OpenCV 官翻 4 - 相机标定与三维重建
  • (LeetCode 每日一题) 1233. 删除子文件夹 (排序)
  • 数据集下载网站
  • aosp15上SurfaceFlinger的dump部分新特性-无Layer相关详细信息输出如何解决?
  • 基于Electron打包jar成Windows应用程序