套接字设置
利用套接字能完成很多丰富得应用,但要想利用套接字实现更复杂得应用,必定会涉及到调整套接字属性,通过调整套接字属性,能够实现广播、组播、地址重用、数据缓冲区以及数据超时处理等功能。
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
参数sockfd----用于指定要操作的套接字
level ----- 用于指定套接字的操作层次,及当前要操作得协议层次
SOL_SOCKET :通用套接字层,用于设置通用套接字
IPPROTO_IP :IP协议层,用于设置IP层
IPPROTO_TCP:TCP协议层,用于设置TCP层
参数optname\optval\optlen是3个相关得参数,optname对应选项名称,及针对那个选项设置,optval是选项所采用得数据结构,optlen是数据结构所占的字节数。以上3个参数的配置取决于level参数得设置。
选项名称 说明 数据类型
========================================================================
SOL_SOCKET
------------------------------------------------------------------------
SO_BROADCAST 允许发送广播数据 int
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
SO_LINGER 延迟关闭连接 struct linger
SO_OOBINLINE 带外数据放入正常数据流 int
SO_RCVBUF接收缓冲区大小int
SO_SNDBUF发送缓冲区大小int
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
SO_RCVTIMEO接收超时struct timeval
SO_SNDTIMEO发送超时 struct timeval
SO_REUSEADDR允许重用本地地址和端口int
SO_TYPE 获得套接字类型 int
SO_BSDCOMPAT 与BSD系统兼容 int
========================================================================
IPPROTO_IP
------------------------------------------------------------------------
IP_HDRINCL 在数据包中包含IP首部 int
IP_OPTINOSIP首部选项 int
IP_TOS服务类型
IP_TTL 生存时间 int
IP_ADD_MEMBERSHIP 组播 sizeof(ip_mreq)
========================================================================
IPPRO_TCP
------------------------------------------------------------------------
TCP_MAXSEGTCP最大数据段的大小 int
TCP_NODELAY 不使用Nagle算法 int
========================================================================
套接字设置应用:
1、数据收发时限设置
这项功能是设置数据包得接收与发送时限,以提升应用程序性能,即在规定的时间内,如果没有数据到来或数据包没有发送成功,则转入相应模块进行处理。
Struct timeval timeout;
timeout . tv_sec = 5;
timeout . tv_usec = 0;
//接收时限
setsockopt( serversocket , SOL_SOCKET, SO_RECVTIMEO,(char *)&timeout, sizeof(timeoout));
//发送时限
setsockopt( serversocket , SOL_SOCKET, SO_SNDTIMEO,(char *)&timeout, sizeof(timeoout));
2、修改数据收发缓存区
在接收与发送数据时,由于实际数据可能远远大于默认缓存区得大小,要想解决这个问题,除了可以循环调用接收与发送函数以外,还可以通过设置SO_RCVBUF或SO_SNDBUF属性得方式完成。
//接收缓冲区
int opt = 1024 * 1024;
setsockopt( serversocket, SOL_SOCKET, SO_RCVBUF,(const char *) &opt, sizeof(opt));
//发送缓冲区
setsockopt( serversocket, SOL_SOCKET, SO_SNDBUF,(const char *) &opt, sizeof(opt));
3、广播设置
在发送数据包的时候,若希望该Socket发送得数据具有广播特性,则要进行下列得设置:
int bBroadcast = 1;
setsockopt(serversocket, SOL_SOCKET, SO_BROADCAST, (const char *) &bBroadcast, sizeof(bBroadcast));
4、直接数据复制
为提升系统性能,在发送或接收数据时,可以主动设置数据不经历由系统缓存区到套接字缓存区的拷贝,这个功能是由设置SO_SNDBUF或SO_RECVBUF的参数值为0来实现的。
Int opt = 0;
//设置发送
setsockopt( serversocket, SOL_SOCKET, SO_SNDBUF,(const char*) &opt, sizeof(opt));
//设置接收
setsockopt( serversocket, SOL_SOCKET, SO_RECVBUF,(const char*) &opt, sizeof(opt));
组播技术
在internet的某些应用中,有时候需要大量用户相互协作,若协作规模比较小,可以采用单播通信方式,直接点对点,单点对点得缺点是不管是信息的发送方还是接收方,都需要维护一个用户列表,代价比较高,有时候也可以采用广播通信方式,但如果是在拥有数十万个节点得网络中,使用广播会很低效,甚至不可能,因为此时大多数得主机对此信息可能不感兴趣。
因此需要一种折中得办法,既能实现小组范围内得互联,又能高校运转,为此,组播就应运而生。
224.0.0.1
编程流程:
1、套接字基本属性
IP_ADD_MEMBERSHIP
若要加入一个组播组,则要在setsockopt()中设置该选项,其中有一个重要的结构体:
struct ip_mreq
{
struct in_addr imr_multiaddr; //指定组播组的地址
struct in_addr imr_interface; // 指定接口得IPV4地址
};
IP_DROP_MEMBERSHIP
用来从某个组播组中退出
IP_MULTICAST_IF
该选项可以修改网络接口,在结构体ip_mreq中定义新的接口
IP_MULTICAST_TTL
该选项用于设置组播报文的数据包的TTL(生存时间),默认值是1,表示数据包只能在本地的子网中传送。
IP_MULTICAST_LOOP
该选项表示组播组中的成员自已也会收到它向本组发送的报文。
2、组播工作流程
服务器:
struct sockaddr_in address;
memset(&address, 0 , sizeof(address));
address . sin_family = AF_INET;
address . sin_port = htons(8888);
address . sin_addr . s_addr = inet_addr(“224.0.0.1”);
客户端:
//在同一个主机上进行组播设置套接口
bind(sockCli,(struct sockaddr*)&addrSer,sizeof(addrSer));
struct ip_mreq multiaddress;
multiaddress . imr_multiaddr.s_addr = inet_addr(“224.0.0.1”); in_addr
multiaddress . imr_interface . s_addr = htonl(INADDR_ANY);
//加入组播组
if ( setsockopt ( client_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multiaddress , sizeof (multiaddress)) < 0)
{
printf(.......)
return 0;
}
//结束时退出组播组
if ( setsockopt ( client_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &multiaddress , sizeof (multiaddress)) < 0)
{
printf(.......)
return 0;
}
socket(AF_INET,SOKC_STREAM\SOCK_DGRAM\SOCK_RAW)
原始套接字
原始套接字是一种套接字底层技术,它工作在网络层,利用原始套接字可以完成以下功能:
1、设置网卡为混杂模式,嗅探当前网络流经本网卡得所有数据包
2、构造各种数据包(IP,ICMP,TCP,UDP),并进行发送
3、进行新协议得验证
原始套接字的创建:
//创建可以获得所有IP层得数据报文的套接字
int rawsock = socket(AF_INET, SOCK_RAW, htons(ETH_P_IP));
协议码 协议名
IPPROTO_ICMP ICMP 协议
ETH_P_IP IP 协议
IPPROTO_TCP TCP 协议
IPPROTO_UDP UDP 协议