#include <cstdio> //引入C标准输入输出头文件,用于在控制台输出信息
#include<sys/socket.h> //引入socket编程相关的头文件
#include <arpa/inet.h> //引入处理网络地址的头文件
#include<string.h> //引入字符串处理的头文件
#include <errno.h> //引入错误处理的头文件
int main() //程序主函数
{
int sfp; //定义一个socket描述符
struct sockaddr_in s_add; //定义一个用于存储地址信息的结构体
unsigned short portnum = 10051; //定义一个端口号。用于绑定socket
struct sockaddr_in serv = { 0 }; //定义一个存储服务端地址信息的结构体,并初始化为0
char on = 1; //定义一个用于设置 socket 选项的变量。
int serv_len = sizeof(serv); //定义一个变量,用于存储服务端地址信息的长度。
int err; //定义一个变量,用于存储错误码。
sfp = socket(AF_INET, SOCK_STREAM, 0);
/*AF_INET: 这个参数指定了使用 IPv4 地址族。AF_INET 表示 Address Family - Internet,用于指定 IPv4。
SOCK_STREAM: 这个参数指定了套接字的类型。SOCK_STREAM 表示面向连接的 TCP 套接字,它提供可靠的、基于流的连接。
0: 这个参数通常是协议的标识符,用于选择特定的传输协议。在一般的情况下,可以使用 0,表示使用默认协议。在实际中,TCP 协议通常是默认的。
返回值: socket 函数返回一个整数,即套接字的描述符。描述符是一个非负整数,它在后续的网络编程中用于标识和操作这个套接字。
*/
if (-1 == sfp) //检查套接字创建是否成功,如果失败则输出错误信息。
{
printf("socket fail ! \r\n");
return -1;
}
printf("socket ok !\n"); //输出套接字创建成功的提示信息。
printf("ip=%s,port=%d\n", inet_ntoa(serv.sin_addr), ntohs(serv.sin_port)); //打印没绑定前的地址
setsockopt(sfp, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));//允许地址的立即重用
sfp: 这是套接字的描述符,表示要设置选项的套接字。
SOL_SOCKET: 这是选项的级别,表示通用套接字选项,适用于所有的套接字。
SO_REUSEADDR: 这是要设置的选项名称,表示允许在绑定地址时立即重用该地址。在网络编程中,这对于服务器程序在绑定地址之前检查端口是否被占用是非常有用的。
&on: 这是指向存储选项值的缓冲区的指针。在这里,on 是一个 char 类型的变量,用于表示启用 (1) 或禁用 (0) SO_REUSEADDR 选项。
sizeof(on): 这是指定选项值的大小,即 on 变量的大小。
这行代码的作用是启用 SO_REUSEADDR 选项,允许在绑定地址时立即重用该地址。这通常用于防止地址被占用错误,特别是在服务器重启后迅速重新启动时。
memset(&s_add, 0, sizeof(struct sockaddr_in));
s_add.sin_family = AF_INET;
s_add.sin_addr.s_addr = inet_addr("192.168.0.117"); //这个ip地址必须是本机上有的
s_add.sin_port = htons(portnum);
if (-1 == bind(sfp, (struct sockaddr *)(&s_add), sizeof(struct sockaddr))) //绑定
{
printf("bind fail:%d!\r\n", errno);
return -1;
}
printf("bind ok !\n"); //输出绑定成功的提示信息。
getsockname(sfp, (struct sockaddr *)&serv, (socklen_t*)&serv_len); //获取本地套接字地址
//打印套接字地址里的ip和端口值
printf("ip=%s,port=%d\n", inet_ntoa(serv.sin_addr), ntohs(serv.sin_port));
return 0;
}