网络编程|04 TCP套接字之bind的函数
前面介绍了socket
函数, 本节介绍bind
函数. 该函数是网络通信时服务端必不可少的函数.
函数原型 bind
函数把一个本地协议地址赋予一个套接字.
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
成功 : 返回0.
【网络编程|04 TCP套接字之bind的函数】失败 : 返回-1.
- bind函数失败最常见的原因是地址已被使用和端口已被绑定, 并且设置errno的值.
errno的值 描述 EADDRINUSE 地址已被使用 EINVAL 端口已被绑定
-
sockfd
是调用socket
函数返回的文件描述符
-
addr
是一个通用套接字地址结构
struct socketaddr{ uint8_t sa_len; sa_family_t sa_family; char sa_data[18]; };
现在我们探讨的是TCP套接字, 而TCP套接字地址结构如下. 其中**in_addr
是linxu中保存IP地址的网络字节序**, 而in_addr_t
是由typedef定义的一个32位无符号类型的整数.
#include
struct socketaddr_in{ uint8_t sa_len; // 为0 sa_family_t sa_family; // 设置域 in_port_t sin_port; // 绑定端口 struct in_addr sin_addr; // 绑定地址 char sa_data[18]; // 为0 }; struct in_addr{ in_addr_t s_addr; };
但是bind
函数的参数只能支持sockaddr
结构, 无法传入sockaddr_in
结构啊. 想要将TCP的结构传入bind函数只能构通过强制转换的方法.
-
addrlen
是参数addr
的大小. 而socklen_t类型是一个无符号整数.
int ret;
struct sockaddr_in sockaddr;
bzero(&sockaddr, sizeof(sockaddr));
// 全部填0
sockaddr.sa_family = AF_INET;
// 设置域
sockaddr.sin_port = htons(port);
// 绑定端口
sockaddr.sin_addr.in_addr = inet_addr(addr);
// 绑定地址int sockfd = socket(AF_INET, SOCK_STREAM, 0);
ret = bind(sockfd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in));
if(ret < 0)
if(errno == EADDRINUSE)
EXIT("port impropriate");
else
EXIT("bind");
如果想要验证端口被绑定和地址已被使用, 可以使用这里代码来验证bind_error.c . 请将代码中的IP地址写成自己本机的IP地址.
首先来验证地址已被使用, 将代码中的62行注释掉, 接着在两个不同的终端调用该程序, 得到的结果就是 :
文章图片
然后验证端口已被绑定的错误, 将62行注释取消, 直接运行一次程序, 结果如下 :
文章图片
总结
- sockfd是从
socket
函数返回的文件描述符 - 套接字地址结构一定要强制转化
推荐阅读
- CVE-2020-16898|CVE-2020-16898 TCP/IP远程代码执行漏洞
- 网络编程基础--HTTP
- 《Unix网络编程》第一卷第三版|《Unix网络编程》第一卷第三版 源码编译
- 计算机网络基础TCP\HTTP\HTTPS
- TCP长连接与段链接
- TCP组件设计篇(详细设计)
- 工具|Wireshark抓包对其字TCP段理解
- 网络|网络编程释疑(TCP连接拔掉网线后会发生什么)
- 服务器未能释放tcp连接,TCP连接的建立和释放
- 用|用 Python 写网络编程(二)