UDP组播服务器

因为项目需要组播发送TS流,所以自己写了一个组播服务器。

组播传输:数据发送者(源数据)将同一数据发送到多个接受者(组播组成员)。无论有多少个接受者,在整个网络链路上,只有一份该数据(在特殊场合,可以节省带宽,减少主干网络阻塞)。

组播报文的目的地址使用的是D类IP地址(224.0.0.0到239.255.255.255)。

使用组播时,注意参数,生命周期(TTL,Time to live)的设置。

UDP组播的基本步骤:
1.创建udp socket
2.bind
3.加入组播组
4.发送/接收数据
5.close

代码:
1.创建udp socket

//调用:createSocket(SOCK_DGRAM)
int createSocket(int type) {
  // Call "socket()" to create a (IPv4) socket of the specified type.
  // But also set it to have the 'close on exec' property (if we can)
  int sock;

#ifdef SOCK_CLOEXEC
  sock = socket(AF_INET, type|SOCK_CLOEXEC, 0);
  if (sock != -1 || errno != EINVAL) return sock;
  // An "errno" of EINVAL likely means that the system wasn't happy with the SOCK_CLOEXEC; fall through and try again without it:
#endif

  sock = socket(AF_INET, type, 0);
#ifdef FD_CLOEXEC
  if (sock != -1) fcntl(sock, F_SETFD, FD_CLOEXEC);
#endif

#ifdef SO_REUSEPORT
  if (setsockopt(sock , SOL_SOCKET, SO_REUSEPORT,
         (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
    socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
    closeSocket(sock );
    return -1;
  }
#endif
  return sock;
}

2.bind

int newSocket = createSocket(SOCK_DGRAM) ;
struct sockaddr_in  m_localAddr;
m_localAddr.sin_family = AF_INET;
m_localAddr.sin_addr.s_addr = INADDR_ANY;
m_localAddr.sin_port = htons(6666);
if (bind(newSocket, (struct sockaddr*)&m_localAddr, sizeof m_localAddr) != 0)
{
    printf("bind error!\n");
    close(newSocket) ;
    return -1;
}

/*
// Set the sending interface for multicasts, if it's not the default:
//m_localAddr.sin_addr.s_addr ==>SendingInterfaceAddr 
  if (SendingInterfaceAddr != INADDR_ANY) {
    struct in_addr addr;
    addr.s_addr = SendingInterfaceAddr;

    if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,
           (const char*)&addr, sizeof addr) < 0) {
      socketErr(env, "error setting outgoing multicast interface: ");
      closeSocket(newSocket);
      return -1;
    }
  }
*/

3.加入组播组

bool socketJoinGroup(int socket,char *groupAddress){

    //if (!IsMulticastAddress(groupAddress)) return True;
    struct ip_mreq imr;
    imr.imr_multiaddr.s_addr = inet_addr(groupAddress);
    imr.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
        (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
        return False;
    }
    return True;
}

4.发送

char buf[1024] ;
struct sockaddr_in groupAddr ;
if (sendto(sockfd, buf, strlen (buf), 0, (struct sockaddr *) &groupAddr , sizeof ( groupAddr )) < 0)
{
.....
}

5.close

close(sockfd)

注意结构:

 struct ip_mreq
    {
        struct in_addr imr_multiaddr;   // 组播组的IP地址。
        struct in_addr imr_interface;   // 本地某一网络设备接口的IP地址。
    };

猜你喜欢

转载自blog.csdn.net/wo_Niu123/article/details/81835456
今日推荐