简介setsockopt和udp的多播(组播)广播 您所在的位置:网站首页 c语言setsockopt函数 简介setsockopt和udp的多播(组播)广播

简介setsockopt和udp的多播(组播)广播

#简介setsockopt和udp的多播(组播)广播| 来源: 网络整理| 查看: 265

Tcp,Udp中的单播/组播/广播 2019年06月27日 1 Setsockopt方法 1.1 setsockopt()函数,用于任意类型、任意状态套接口的设置选项值。 int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen); sockfd:标识一个套接口的描述字。 level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。 optname:需设置的选项。 optval:指针,指向存放选项待设置的新值的缓冲区。 optlen:optval缓冲区长度。

若无错误发生,setsockopt()返回0,否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。 1.2 setsockopt()的几种例子 网上搜索setsockopt()用法几乎都是SOL_SOCKET的设置,这里总结一下IPPROTO_IP层的设置。

可取值 setsockopt getsockopt IP_MULTICAST_LOOP 支持 支持 IP_MULTICAST_TTL 支持 支持 IP_MULTICAST_IF 支持 支持 IP_ADD_MEMBERSHIP 支持 不支持 IP_DROP_MEMBERSHIP 支持 不支持

IP_MULTICAST_LOOP

当接收者加入到一个多播组以后,再向这个多播组发送数据,这个字段的设置是否允许再返回到本身。

int loop=1; //1:on 0:off setsockopt(sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop)); 2. IP_MULTICAST_TTL 默认情况下,多播报文的TTL被设置成了1,也就是说到这个报文在网络传送的时候,它只能在自己所在的网络传送,当要向外发送的时候,路由器把TTL减1以后变成了0,这个报文就已经被Discard了。例:

char ttl; ttl = 2; setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char*)ttl, sizeof(ttl)); IP_MULTICAST_IF

发送多播报文时用的本地接口,默认情况下被设置成了本地接口的第一个地址。 未完

IP_ADD_MEMBERSHIP

这个option和下面的option是实现多播必不可少的,它用于加入一个多播组,例:

struct ip_mreq ipmr; ipmr.imr_interface.s_addr = htonl(INADDR_ANY); ipmr.imr_multiaddr.s_addr = inet_addr(“234.5.6.7”); setsockopt(s, IPPROTO_IP, IP_ADDR_MEMBERSHIP, (char*)&ipmr, sizeof(ipmr));

IP_DROP_MEMBERSHIP

用于离开一个多播组,使用方法同IP_ADDR_MEMBERSHIP。

struct ip_mreq ipmr; int len; setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&ipmr, &len); 1.设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket,而经历TIME_WAIT的过程。 BOOL bReuseaddr = TRUE; setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( const char* )&bReuseaddr, sizeof( BOOL ) ); 2. 如果要已经处于连接状态的soket在调用closesocket()后强制关闭,不经历TIME_WAIT的过程: BOOL bDontLinger = FALSE; setsockopt( s, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof( BOOL ) ); 3.在send(),recv()过程中有时由于网络状况等原因,收发不能预期进行,可以设置收发时限: int nNetTimeout = 1000; //1秒 //发送时限 setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof( int ) ); //接收时限 setsockopt( socket, SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) ); 4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中如果发送或是接收的数据量比较大,可以设置socket缓冲区,避免send(),recv()不断的循环收发: // 接收缓冲区 int nRecvBufLen = 32 * 1024; //设置为32K setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( const char* )&nRecvBufLen, sizeof( int ) ); //发送缓冲区 int nSendBufLen = 321024; //设置为32K setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( const char )&nSendBufLen, sizeof( int ) ); 5.在发送数据的时,不执行由系统缓冲区到socket缓冲区的拷贝,以提高程序的性能: int nZero = 0; setsockopt( socket, SOL_SOCKET, SO_SNDBUF, ( char * )&nZero, sizeof( nZero ) ); 6.在接收数据时,不执行将socket缓冲区的内容拷贝到系统缓冲区: int nZero = 0; setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( char * )&nZero, sizeof( int ) ); 7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性: BOOL bBroadcast = TRUE; setsockopt( s, SOL_SOCKET, SO_BROADCAST, ( const char* )&bBroadcast, sizeof( BOOL ) ); 8.在client连接服务器过程中,如果处于非阻塞模式下的socket在connect()的过程中可以设置connect()延时,直到accpet()被调用(此设置只有在非阻塞的过程中有显著的作用,在阻塞的函数调用中作用不大) BOOL bConditionalAccept = TRUE; setsockopt( s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, ( const char* )&bConditionalAccept, sizeof( BOOL ) ); 9.如果在发送数据的过程中send()没有完成,还有数据没发送,而调用了close(socket),以前一般采取的措施是shutdown(s,SD_BOTH),但是数据将会丢失。 某些具体程序要求待未发送完的数据发送出去后再关闭socket,可通过设置让程序满足要求: struct linger { u_short l_onoff; u_short l_linger; }; struct linger m_sLinger; m_sLinger.l_onoff = 1; //在调用close(socket)时还有数据未发送完,允许等待 // 若m_sLinger.l_onoff=0;则调用closesocket()后强制关闭 m_sLinger.l_linger = 5; //设置等待时间为5秒 setsockopt( s, SOL_SOCKET, SO_LINGER, (const char*)&m_sLinger, sizeof(struct linger));

2 广播地址 2.1 广播地址: 广播地址是专门用于同时向网络中所有工作站进行发送的一个地址。在使用TCP/IP 协议的网络中,主机号为全1的IP地址为广播地址。例如,对于 :192.168.199.0(掩码:255.255.255.0)网段,其广播地址为192.168.199.255 (255 即为2进制的11111111 ),当发出一个目的地址为192.168.199.255的分组时,它将被分发给该网段上的所有计算机。 2.2 直接广播地址

指Host部分全为1的广播地址。如:192.168.199.255。当某机器发出目的地址为直接广播(如:192.168.199.255)时,路由器通过查找路由表可以转发,直到该网段。 2.3 受限广播地址

也称本地广播地址,它不被路由发送,但会被送到相同物理网络段上的所有主机,IP地址的网络号和主机号 全为1就是地址255.255.255.255,当某机器发出目的地址为本地广播时,路由器不会转发该包。所以该包只能限制在本网段 2.4 代码示例 server.cpp

#include #include #include #include #include #include #include #include #include using namespace std;

int main() { int sockfd; struct sockaddr_in saddr; int r; char recvline[1025]; struct sockaddr_in presaddr; socklen_t len;

sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(9999); bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)); while (1) { r = recvfrom(sockfd, recvline, sizeof(recvline), 0 , (struct sockaddr*)&presaddr, &len); if (r 19 int sock; 20 struct sockaddr_in mcast_addr; 21 sock=socket(AF_INET,SOCK_DGRAM,0); 22 if(sock==-1) 23 { 24 cout 41 cout 24 cout 43 cout 63 addr_len=sizeof(local_addr); 64 memset(buff,0,BUFF_SIZE); 65 n=recvfrom(sock,buff,BUFF_SIZE,0,(struct sockaddr*)&local_addr,&addr_len); 66 if(n==-1) 67 { 68 cout 13 setvbuf(stdout,NULL,_IONBF,0); 14 fflush(stdout); 15 int sock=-1; 16 if((sock=socket(AF_INET,SOCK_DGRAM,0))-1) 17 { 18 cout 37 sleep(1); 38 char msg[]={“the message broadcast”}; 39 int ret=sendto(sock,msg,strlen(msg),0,(sockaddr*)&addrto,nlen);//向广播地址发布消息 40 if(ret 47 printf(“ok\n”); 48 } 49 } 50 return 0; 51 } 3.3.2 UDP广播客户端代码: #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 11 12 using namespace std; 13 int main() 14 { 15 setvbuf(stdout,NULL,_IONBF,0); 16 fflush(stdout); 17 struct sockaddr_in addrto; 18 bzero(&addrto,sizeof(struct sockaddr_in)); 19 addrto.sin_family=AF_INET; 20 addrto.sin_addr.s_addr=htonl(INADDR_ANY); 21 addrto.sin_port=htons(6000); 22 socklen_t len=sizeof(addrto); 23 int sock=-1; 24 if((sock=socket(AF_INET,SOCK_DGRAM,0))-1) 25 { 26 cout 39 cout 48 cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有