一、setsockopt函数
1.1、函数
头文件:
#include <sys/socket.h>
函数:int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
功能:设置一个套接字的选项(属性)
参数:
socket:文件描述符
level:协议层次
SOL_SOCKET 套接字层次
IPPROTO_TCP TCP层次
IPPROTO_IP IP层次
option_name:选项的名称
SO_BROADCAST 允许发送广播数据(SOL_SOCKET层次的)
option_value:设置的选项的值
第一种设置: int类型的值,存储的是bool的数据(1和0)0 不允许
1 允许第二种设置: ip_mreq{}类型
struct ip_mreq
{
struct in_addr imr_multiaddr; //组播ip地址
struct in_addr imr_interface; //主机地址
};
INADDR_ANY 任意主机地址(自动获取你的主机地址)
option_len:option_value的长度
返回值:
成功:0
失败:‐1
1.2、参数选项介绍图
二、初学者重点掌握四种设置setsockopt函数:
2.1、第一种:发送者需要设置允许用广播发送数据(用与UDP广播使用)
看1.2图所示:level选择 SOL_SOCKET , optname选择 SO_BROADCAST
数据类型为int 使用第一种设置。
2.1.1、代码如下:
int on =1;
if(setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on))==-1)
{
perror("fail to setsockopt");
exit(1);
}
2.2、第二种:接收者需要设置setsockopt函数加入多播组(用于UDP多播使用)
看1.2图所示,level选择 IPPROTO_IP , optname选择 IP_ADD_MEMBERSHIP
数据类型为 ip_mreq{} 使用第二种设置
2.2.1、代码如下:
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr=inet_addr(argv[1]); //argv[1]:传进来的是加入的多播地址
mreq.imr_interface.s_addr=INADDR_ANY; //INADDR_ANY:自动获取本机的地址
socklen_t optlen =sizeof(mreq);
if(setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,optlen) < 0)
{
perror("fail to setsockopt");
exit(1);
}
2.3、第三种:设置TCP/UDP 允许重用本地地址
为什么要设置。理由:服务器和客户端正常通信时,手动异常关闭 server 端进程,再次运行开启 server 端程序会在 bind 函数位置报错,造成无法连接。
查阅资料后发现应该是地址或端口冲突了,尝试在 bind 函数前添加 setsockopt 函数增加复用功能.
经过修改测试,重用本地端口未能解决该问题,设置重用本地地址可以解决。
看1.2图所示:level选择 SOL_SOCKET , optname选择 SO_REUSEADDR
数据类型为int 使用第一种设置。
2.3.1、代码如下
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ==-1 )
{
perror("fail to setsockopt");
}
2.4、第四种:设置TCP/UDP 允许重用本地端口
当我们结束一个服务器程序时,再一次打开此服务器进程同一个端口号,出现错误,必须要换一个端口号才行。
为了解决这个问题,我们需要使用setsockopt函数设置允许重用本地端口。
看1.2图所示:level选择 SOL_SOCKET , optname选择 SO_REUSEPORT
数据类型为int 使用第一种设置。
2.4.1、代码如下
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) ==-1 )
{
perror("fail to setsockopt");
}