因为项目需要组播发送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地址。
};