一、单播,组播,广播
单播(unicast): 是指封包在计算机网络的传输中,目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如一切基于TCP的协议。
组播(multicast): 也叫多播, 多点广播或群播。 指把信息同时传递给一组目的地址。它使用策略是最高效的,因为消息在每条网络链路上只需传递一次,而且只有在链路分叉的时候,消息才会被复制。
广播(broadcast):是指封包在计算机网络中传输时,目的地址为网络中所有设备的一种传输方式。实际上,这里所说的“所有设备”也是限定在一个范围之中,称为“广播域”。
在Linux运行ifconfig, 如果网卡信息中包含UP BROADCAST RUNNING MULTICAST,则支持广播和组播。
每次只有两个实体相互通信,发送端和接收端都是唯一确定的。在IPv4网络中,0.0.0.0到223.255.255.255属于单播地址。
你对小月月喊“小月月”,那么只有小月月回过头来答应你。
组播是一种通过使用一个组播地址将数据在同一时间以高效的方式发往处于TCP/IP网络上的多个接收者的协议。
互联网架构师戴夫·克拉克是这样描述IP组播的:“你把数据包从一头放进去,网络就会试图将它们传递到想要得到它们的人那里。”
组播报文的目的地址使用D类IP地址, D类地址不能出现在IP报文的源IP地址字段。
你在大街上大喊一声“美女”, 会有一群女性回头看你。
并非所有的计算机网络都支持广播,例如X.25网络和帧中继都不支持广播,而且也没有在“整个互联网范围中”的广播。IPv6亦不支持广播,广播相应的功能由任播(anycast)代替。通常,广播都是限制在局域网中的,比如以太网或令牌环网络。因为广播在局域网中造成的影响远比在广域网中小得多。以太网和IPv4网都用全1的地址表示广播,分别是ff:ff:ff:ff:ff:ff和255.255.255.255。令牌环网络使用IEEE 802.2控制域中的一个特殊值来表示广播。
你在公司大喊一声“放假了”, 全部同事都会响应,大叫爽死了。
224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255是公用组播地址,Internetwork Control Block;
224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。
UDP广播服务端代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<sys/socket.h>
4 #include<unistd.h>
5 #include<sys/types.h>
6 #include<netdb.h>
7 #include<netinet/in.h>
8 #include<arpa/inet.h>
9 #include<string.h>
10 using namespace std;
11 int main()
12 {
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<<"sock error"<<endl;
19 return -1;
20 }
21 const int opt=-1;
22 int nb=0;
23 nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char*)&opt,sizeof(opt));//设置套接字类型
24 if(nb==-1)
25 {
26 cout<<"set socket error...\n"<<endl;
27 return -1;
28 }
29 struct sockaddr_in addrto;
30 bzero(&addrto,sizeof(struct sockaddr_in));
31 addrto.sin_family=AF_INET;
32 addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST);//套接字地址为广播地址
33 addrto.sin_port=htons(6000);//套接字广播端口号为6000
34 int nlen=sizeof(addrto);
35 while(1)
36 {
37 sleep(1);
38 char msg[]={"the message broadcast"};
39 int ret=sendto(sock,msg,strlen(msg),0,(sockaddr*)&addrto,nlen);//向广播地址发布消息
40 if(ret<0)
41 {
42 cout<<"send error...\n"<<endl;
43 return -1;
44 }
45 else
46 {
47 printf("ok\n");
48 }
49 }
50 return 0;
51 }
UDP广播客户端代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<sys/socket.h>
4 #include<unistd.h>
5 #include<sys/types.h>
6 #include<netdb.h>
7 #include<netinet/in.h>
8 #include<arpa/inet.h>
9 #include<string.h>
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<<"socket error..."<<endl;
27 return -1;
28 }
29 const int opt=-1;
30 int nb=0;
31 nb=setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char*)&opt,sizeof(opt));
32 if(nb==-1)
33 {
34 cout<<"set socket errror..."<<endl;
35 return -1;
36 }
37 if(bind(sock,(struct sockaddr*)&(addrto),len)==-1)
38 {
39 cout<<"bind error..."<<endl;
40 return -1;
41 }
42 char msg[100]={0};
43 while(1)
44 {
45 int ret=recvfrom(sock,msg,100,0,(struct sockaddr*)&addrto,&len);
46 if(ret<=0)
47 {
48 cout<<"read error..."<<endl;
49 }
50 else
51 {
52 printf("%s\t",msg);
53 }
54 sleep(1);
55 }
56 return 0;
57 }
多播的程序设计使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的
3、多播程序设计的框架
要进行多播的编程,需要遵从一定的编程框架。多播程序框架主要包含套接字初始化、设置多播超时时间、加入多播组、发送数据、接收数据以及从多播组中离开几个方面。其步骤如下:
(1)建立一个socket。
(2)然后设置多播的参数,例如超时时间TTL、本地回环许可LOOP等。
(3)加入多播组。
(4)发送和接收数据。
(5)从多播组离开。
4、多播实现代码
服务端代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<sys/socket.h>
4 #include<netdb.h>
5 #include<sys/types.h>
6 #include<arpa/inet.h>
7 #include<netinet/in.h>
8 #include<unistd.h>
9 #include<stdlib.h>
10 #include<string.h>
11 #define MCAST_PORT 8888
12 #define MCAST_ADDR "224.0.0.88" // 多播地址
13 #define MCAST_DATA "BROADCAST TEST DATA" // 多播内容
14 #define MCAST_INTERVAL 5 //多播时间间隔
15 using namespace std;
17 int main()
18 {
19 int sock;
20 struct sockaddr_in mcast_addr;
21 sock=socket(AF_INET,SOCK_DGRAM,0);
22 if(sock==-1)
23 {
24 cout<<"socket error"<<endl;
25 return -1;
26 }
27 memset(&mcast_addr,0,sizeof(mcast_addr));
28 mcast_addr.sin_family=AF_INET;
29 mcast_addr.sin_addr.s_addr=inet_addr(MCAST_ADDR);
30 mcast_addr.sin_port=htons(MCAST_PORT);
31 while(1)
32 { //向局部多播地址发送多播内容
33 int n=sendto(sock,MCAST_DATA,sizeof(MCAST_DATA),0,(struct sockaddr*)&mcast_addr,sizeof(mcast_addr));
34 if(n<0)
35 {
36 cout<<"send error"<<endl;
37 return -2;
38 }
39 else
40 {
41 cout<<"send message is going ...."<<endl;
42 }
43 sleep(MCAST_INTERVAL);
44
45 }
46 return 0;
47 }
客户端代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<string.h>
5 #include<sys/types.h>
6 #include<unistd.h>
7 #include<sys/socket.h>
8 #include<netdb.h>
9 #include<arpa/inet.h>
10 #include<netinet/in.h>
11 #define MCAST_PORT 8888
12 #define MCAST_ADDR "224.0.0.88" /*一个局部连接多播地址,路由器不进行转发*/
13 #define MCAST_INTERVAL 5 //发送时间间隔
14 #define BUFF_SIZE 256 //接收缓冲区大小
15 using namespace std;
16 int main()
17 {
18 int sock;
19 struct sockaddr_in local_addr;
20 int err=-1;
21 sock=socket(AF_INET,SOCK_DGRAM,0);
22 if(sock==-1)
23 {
24 cout<<"sock error"<<endl;
25 return -1;
26 }
27 /*初始化地址*/
28 local_addr.sin_family=AF_INET;
29 local_addr.sin_addr.s_addr=htonl(INADDR_ANY);
30 local_addr.sin_port=htons(MCAST_PORT);
31 /*绑定socket*/
32 err=bind(sock,(struct sockaddr*)&local_addr,sizeof(local_addr));
33 if(err<0)
34 {
35 cout<<"bind error"<<endl;
36 return -2;
37 }
38 /*设置回环许可*/
39 int loop=1;
40 err=setsockopt(sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
41 if(err<0)
42 {
43 cout<<"set sock error"<<endl;
44 return -3;
45 }
46 struct ip_mreq mreq;/*加入广播组*/
47 mreq.imr_multiaddr.s_addr=inet_addr(MCAST_ADDR);//广播地址
48 mreq.imr_interface.s_addr=htonl(INADDR_ANY); //网络接口为默认
49 /*将本机加入广播组*/
50 err=setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
51 if(err<0)
52 {
53 cout<<"set sock error"<<endl;
54 return -4;
55 }
56 int times=0;
57 socklen_t addr_len=0;
58 char buff[BUFF_SIZE];
59 int n=0;
60 /*循环接受广播组的消息,5次后退出*/
61 for(times=0;;times++)
62 {
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<<"recv error"<<endl;
69 return -5;
70 }
71 /*打印信息*/
72 printf("RECV %dst message from server : %s\n",times,buff);
73 sleep(MCAST_INTERVAL);
74 }
75 /*退出广播组*/
76 err=setsockopt(sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq));
77 close(sock);
78 return 0;
79 }
二、开发实例
本项目:是将视频通过以太网发送至qt,实时显示。板卡是多个板卡与上位机,多对一的关系。和板卡与板卡一对一的通信。
定义了三个业务来管理通信。
1、dsp首先定时发送bit,通过组播的方式,与qt通信,上报本地ip,选择组播,是dsp要与qt之间通信,需要互相知道ip,但是,第一次通信时,dsp是不知道qt的ip,pc端也不知道dsp的ip,只能通过dsp,在同一个网段,组播方式,上报本地ip,建立联系。并每秒发送,以确保dsp与pc端连接正常。(说明,建立连接上报时,qt可以获取dsp地址,也可以在数据段,填写dsp ip。dsp与qt事先沟通好的,发送组播地址,端口号,不可更改,否则qt与dsp无法约定通信)
2、pc端qt上位机,在上一步获得dsp的ip,这时pc,可以随意读取,修改dsp的本地配置信息,包括ip,端口号,流地址,可随意配置流地址,端口号,选择单播或组播方式发送。
3、dsp上电开机时,dsp将读取本地文件配置,选择流发送地址,如若qt修改dsp,dsp保存修改后的地址到本地配置文件,选择新的地址发送。发送方式,将根据设置的ip地址类型,选择单播,组播,广播
单播:xxx.xxx.xxx.xxx //( < 224) 192.168.0.1
组播:224.xxx.xxx.xxx //(224< ip < 239) 224.1.1.1
广播:xxx.xxx.xxx.255 //( 255) 192.168.0.255
类型1 数据流发送(dsp 与pc)
上行:
DSP发送单播至PC((目标地址:PC IP, 10005)
或
DSP发送组播至PC(目标地址:224.1.1.4, 10005)类型1 数据流发送(dsp与dsp)
上行:
DSP1发送单播至DSP2((目标地址:DSP2 IP, 8080)
下行:
DSP2发送单播至DSP1(目标地址:DSP1 IP, 8088)
或
上行:
DSP1发送组播至DSP2(目标地址:224.1.1.4, 8088)
下行:
DSP2发送组播至DSP1(目标地址:224.1.1.4, 8080)>或
上行:
DSP1发送广播至DSP2(目标地址:xxx.xxx.xxx.255, 8088)
下行:
DSP2发送广播至DSP1(目标地址:xxx.xxx.xxx.255, 8080)
类型2 BIT通信(1S为周期上报至上位机
上行:
DSP发送组播至PC(目标地址:224.1.1.4, 10002)
类型3 配置管理通信(dsp与qt)
上行:
DSP发送单播至PC(目标地址:下行源地址,10003)
下行:
PC发送单播至DSP1(目标地址:DSP IP, 10003)
本项目,板卡与板卡直接网线通信时,可以选择单播,组播,广播
但是中间经过其他如光纤时,是不可以单播的,因为,要建立握手,rtp通信,是需要两个设备能够网络通信的,否则发送没有回应是无法建立握手的,只能选择组播,广播,不需要握手,就能通信。
void *xine_xmalloc(SX_S32 size)
{
void *p = malloc(size);
if( p == NULL)
{
return NULL;
}
memset(p, 0, size);
return p;
}
void xine_free(void *p)
{
if( p )
{
free(p);
}
return;
}
void xine_freep(void *arg)
{
if( arg )
{
void **ptr = (void **)arg;
if( *ptr )
{
xine_free(*ptr);
*ptr = NULL;
}
}
}
SX_BOOL get_local_ip( SX_S64 sock_fd, SX_S8 *ip, SX_S8 *dev_name )
{
SX_BOOL ret = SX_FALSE;
struct sockaddr_in *sin;
SX_S8 *tmp = NULL;
struct ifreq ifr;
memset( &ifr, 0, sizeof( struct ifreq ) );
strncpy( ifr.ifr_name, dev_name, IFNAMSIZ );
ifr.ifr_name[IFNAMSIZ-1] = '\0';
ifr.ifr_addr.sa_family = PF_INET;
if ( ioctl( sock_fd, SIOCGIFADDR, (char *)&ifr ) != -1 )
{
sin = ( struct sockaddr_in * )&ifr.ifr_addr;
tmp = inet_ntoa(*(struct in_addr *)(char *)&sin->sin_addr);
strcpy( ip, tmp );
TRACE(DL_INFO, "get local ip %s \n", ip );
ret = SX_TRUE;
}
else
{
TRACE(DL_ERROR, "get local ip Error \n");
}
return ret;
}
SX_BOOL join_multicast_group( SX_S64 sock_fd, SX_S8 *ip, SX_S32 port, SX_S8 *dev_name )
{
#ifdef WIN32
struct ip_mreq mreq;
unsigned long sel_addr;
sel_addr = inet_addr( ip );
mreq.imr_multiaddr.s_addr = sel_addr;
mreq.imr_interface.s_addr = 0;
if ( 0 != setsockopt( sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (SX_S8 *)&mreq, sizeof( mreq ) ) )
{
TRACE(DL_ERROR, "setsockopt failed \n");
return SX_FALSE;
}
return SX_TRUE;
#else
// join multicast group
struct hostent *group;
struct ip_mreq mreq;
SX_S8 multi_ip[16];
SX_S8 local_ip[16];
struct in_addr in_addr;
unsigned long sel_addr;
SX_S32 sock_len;
struct sockaddr_in peer_addr;
bzero( &mreq, sizeof( struct ip_mreq ) );
memset( multi_ip, 0, sizeof( multi_ip ) );
strcpy( multi_ip, (SX_S8 *)ip );
// is gethostbyname obsolescent ?
if ( ( group = gethostbyname( multi_ip ) ) == ( struct hostent * ) 0 )
{
TRACE(DL_ERROR, "gethostbyname failed \n");
return SX_FALSE;
}
memset( local_ip, 0, sizeof( local_ip ) );
if ( !get_local_ip( sock_fd, local_ip, dev_name ) )
{
TRACE(DL_ERROR, "get_local_ip failed \n");
return SX_FALSE;
}
sel_addr = inet_addr( local_ip );
if ( setsockopt( sock_fd, IPPROTO_IP, IP_MULTICAST_IF,(char *)&sel_addr, sizeof( sel_addr ) ) < 0 )
{
TRACE(DL_ERROR, "gethostbyname failed \n");
return SX_FALSE;
}
// add to group.
bcopy( (void *)group->h_addr, (void *)&in_addr, group->h_length);
bcopy( &in_addr, &mreq.imr_multiaddr.s_addr, sizeof( struct in_addr ) );
mreq.imr_interface.s_addr = inet_addr( local_ip );
sock_len = sizeof( struct sockaddr_in );
memset( &peer_addr, 0, sock_len );
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons( port );
if ( ( inet_pton( AF_INET, multi_ip, &peer_addr.sin_addr) <= 0 ) ||
( -1 == setsockopt( sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ) )
)
{
TRACE(DL_ERROR, "inet_pton/setsockopt failed \n");
return SX_FALSE;
}
return SX_TRUE;
#endif
}
1、配置协议,提供接收和发送函数,供qt读写本dsp配置,单播方式
#if 1
void Cfg_Server_Close(PT_SERVER handle)
{
if( handle )
{
close(handle->sockfd);
if( handle->pszSendBuf )
{
xine_freep(&handle->pszSendBuf);
}
if( handle->pszRecvBuf )
{
xine_freep(&handle->pszRecvBuf);
}
xine_freep(&handle);
}
return;
}
//unicast receive and send 192.168.0.163
PT_SERVER Cfg_Server_Open(const SX_S8 *recv_ip, SX_S16 recv_port, SX_S8 * dev_name)
{
PT_SERVER handle = (PT_SERVER)xine_xmalloc(sizeof(T_SERVER));
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return NULL;
}
handle->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(handle->sockfd < 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
Cfg_Server_Close(handle);
return NULL;
}
SX_S32 mode = 0;
if( -1 == ioctl(handle->sockfd, FIONBIO, &mode) ) //for nonblock
{
TRACE(DL_ERROR, "DL_ERROR\n");
Cfg_Server_Close(handle);
return NULL;
}
memset( &(handle->servaddr), 0, sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
SX_S8 ip[20] = {0};
strcpy( ip, recv_ip );
#if 1
handle->servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#else
if( inet_pton( AF_INET, ip, &(handle->servaddr.sin_addr) ) <= 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
SERVER_Close(handle);
return NULL;
}
/*
bzero( &(handle->servaddr), sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
//inet_pton(AF_INET, send_ip, &(handle->servaddr.sin_addr));
handle->servaddr.sin_addr.s_addr = inet_addr(ip);
*/
#endif
handle->servaddr.sin_port = htons(recv_port);
if( bind(handle->sockfd, (struct sockaddr *)&(handle->servaddr), sizeof(handle->servaddr)) < 0 )
{
TRACE(DL_ERROR, "DL_ERROR\n");
close(handle->sockfd);
Cfg_Server_Close(handle);
return NULL;
}
SX_S32 address[4] = {0, 0, 0, 0};
if( 4 == sscanf( (SX_S8 *)ip, "%d.%d.%d.%d", &address[0], &address[1], &address[2], &address[3] ) )
{
if( (address[0] >= 224) && (address[0] <= 239) )
{
if( !join_multicast_group(handle->sockfd, ip, recv_port, dev_name) )
{
TRACE(DL_WARNING, "join_multicast_group failed \n");
}
}
}
#if 0 //get default sendbuf size 160k
int opt_val1=0,opt_val2=0;
socklen_t opt_len = sizeof(opt_val1);
getsockopt(handle->sockfd, SOL_SOCKET, SO_SNDBUF, &opt_val1,&opt_len);
getsockopt(handle->sockfd, SOL_SOCKET, SO_RCVBUF, &opt_val2,&opt_len);
while(1)
{
printf("SNDBUF = %dk RCVBUF = %dk \r\n", opt_val1 / 1024, opt_val2 / 1024);
}
#endif
#if 1
int nSendBufLen = 10*1024; //set sendbuf size 160k
setsockopt(handle->sockfd, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBufLen, sizeof(int));
setsockopt(handle->sockfd, SOL_SOCKET, SO_RCVBUF, ( const char* )&nSendBufLen, sizeof(int));
#endif
//int loop=0; //Off
//setsockopt( handle->sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop) );
handle->cliaddr_len = sizeof(handle->cliaddr);
handle->pszRecvBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszRecvBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Cfg_Server_Close(handle);
return NULL;
}
handle->pszSendBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszSendBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Cfg_Server_Close(handle);
return NULL;
}
TRACE(DL_INFO, "ip:%s, port:%d, dev:%s\n", recv_ip, recv_port, dev_name);
return handle;
}
SX_S32 Cfg_Server_Receive(PT_SERVER handle, void *buf, SX_S32 timeoutMs )
{
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_S32 ret, sret, retval;
SX_S64 max_fd;
fd_set readfds;
struct timeval tv;
FD_ZERO(&readfds);
FD_SET( handle->sockfd, &readfds );
max_fd = handle->sockfd;
tv.tv_sec = timeoutMs/1000;
tv.tv_usec = (timeoutMs%1000)*1000;
retval = select( max_fd + 1, &readfds, NULL, NULL, &tv );
if ( retval > 0 )
{
if( buf ){
sret = recvfrom( handle->sockfd, (SX_S8 *)buf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr), &(handle->cliaddr_len) );
}
else{
sret = recvfrom( handle->sockfd, handle->pszRecvBuf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr), &(handle->cliaddr_len) );
handle->s32RecvLen = sret;
}
if ( sret > 0 )
{
ret = sret;
}
else
{
ret = 0; // no data;
}
//strcpy( IP, inet_ntoa( handle->cliaddr.sin_addr ) ); //client IP
//*port = ntohs( handle->cliaddr.sin_port ); //client Port
}
else if ( retval == 0 )
{
// timeout
ret = 0;
}
else
{
// error
ret = -1;
}
//if( ret > 0 )
// TRACE(DL_INFO, "SERVER_Receive:%d\n", ret);
return ret;
}
SX_S32 Cfg_Server_Send(PT_SERVER handle, void *buf, SX_S32 len, struct sockaddr *dst)
{
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_S32 length;
if( buf )
{
length = MIN(len, UDP_MAX_LEN);
if( dst )
return sendto( handle->sockfd, (const SX_S8 *)buf, length, 0, (struct sockaddr *)dst, sizeof(struct sockaddr_in) );
else
return sendto( handle->sockfd, (const SX_S8 *)buf, length, 0, (struct sockaddr *)&(handle->cliaddr), sizeof(handle->cliaddr) );
}
else
{
length = MIN(handle->s32SendLen, UDP_MAX_LEN);
if( dst )
return sendto( handle->sockfd, handle->pszSendBuf, length, 0, (struct sockaddr *)dst, sizeof(struct sockaddr_in) );
else
return sendto( handle->sockfd, handle->pszSendBuf, length, 0, (struct sockaddr *)&(handle->cliaddr), sizeof(handle->cliaddr) );
}
}
#endif
2、上报bit和配置服务。
客户自定义app,开机读取本dsp的bit,对比版本号,确保配置已是最新状态,如若已更新,不发送配置,如若为更新,将下发配置,并更新版本号。
本dsp,将提供主动每秒组播发送bit至本qt。本提供同一套接字监听客户app,组播方式下发的,读取本dsp,bit。和下发配置命令。
#if 1
void Bit_Server_Close1(PT_CLIENT handle)
{
if( handle )
{
close(handle->sockfd);
if( handle->pszSendBuf )
{
xine_freep(&handle->pszSendBuf);
}
if( handle->pszRecvBuf)
{
xine_freep(&handle->pszRecvBuf);
}
xine_freep(&handle);
}
return;
}
// unicast/boardcast receive 192.168.0.163 , multicast send 224.1.1.4
PT_CLIENT Bit_Server_Open1(const SX_S8 *recv_ip, SX_S16 recv_port,const SX_S8 *send_ip, SX_S16 send_port,SX_S8 * dev_name)
{
PT_CLIENT handle = (PT_CLIENT)xine_xmalloc(sizeof(T_CLIENT));
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return NULL;
}
handle->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(handle->sockfd < 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
Bit_Server_Close1(handle);
return NULL;
}
SX_S32 mode = 0;
if( -1 == ioctl(handle->sockfd, FIONBIO, &mode) ) //for nonblock
{
TRACE(DL_ERROR, "DL_ERROR\n");
Bit_Server_Close1(handle);
return NULL;
}
bzero( &(handle->servaddr), sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
SX_S8 ip[20] = {0};
strcpy( ip, recv_ip);
#if 1
handle->servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#else
if( inet_pton( AF_INET, ip, &(handle->servaddr.sin_addr) ) <= 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
SERVER_Close(handle);
return NULL;
}
bzero( &(handle->servaddr), sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
inet_pton(AF_INET, recv_ip, &(handle->servaddr.sin_addr));
handle->servaddr.sin_addr.s_addr = inet_addr(ip);
#endif
handle->servaddr.sin_port = htons(recv_port);
handle->servaddr_len = sizeof(handle->servaddr);
if( bind(handle->sockfd, (struct sockaddr *)&(handle->servaddr), sizeof(handle->servaddr)) < 0 )
{
TRACE(DL_ERROR, "DL_ERROR\n");
//close(handle->sockfd);
Bit_Server_Close1(handle);
return NULL;
}
SX_S32 address[4] = {0, 0, 0, 0};
if( 4 == sscanf( (SX_S8 *)ip, "%d.%d.%d.%d", &address[0], &address[1], &address[2], &address[3] ) )
{
if( (address[0] >= 224) && (address[0] <= 239) )
{
if( !join_multicast_group(handle->sockfd, ip, recv_port, dev_name) )
{
TRACE(DL_WARNING, "join_multicast_group failed \n");
}
}
}
//int loop=0; //Off
//setsockopt( handle->sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop) );
handle->cliaddr_len1 = sizeof(handle->cliaddr1);
bzero( &(handle->cliaddr2), sizeof(handle->cliaddr2));
handle->cliaddr2.sin_family = AF_INET;
handle->cliaddr2.sin_addr.s_addr = inet_addr(send_ip);
handle->cliaddr2.sin_port = htons(send_port);
handle->cliaddr_len2 = sizeof(handle->cliaddr2);
handle->pszRecvBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszRecvBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Bit_Server_Close1(handle);
return NULL;
}
handle->pszSendBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszSendBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Bit_Server_Close1(handle);
return NULL;
}
TRACE(DL_INFO, "sendIP:%s, sendPort:%d\n", send_ip, send_port );
return handle;
}
SX_S32 Bit_Server_Receive1(PT_CLIENT handle, void *buf, SX_S32 timeoutMs )
{
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_S32 ret=-1, sret=0, retval=0;
SX_S64 max_fd;
fd_set readfds;
struct timeval tv;
FD_ZERO(&readfds);
FD_SET( handle->sockfd, &readfds );
max_fd = handle->sockfd;
tv.tv_sec = timeoutMs/1000;
tv.tv_usec = (timeoutMs%1000)*1000;
retval = select( max_fd + 1, &readfds, NULL, NULL, &tv );
if ( retval > 0 )
{
if( buf ){
sret = recvfrom( handle->sockfd, (SX_S8 *)buf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr1), &(handle->cliaddr_len1) );
handle->s32RecvLen = sret;
}
else{
sret = recvfrom( handle->sockfd, handle->pszRecvBuf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr1), &(handle->cliaddr_len1) );
handle->s32RecvLen = sret;
}
if ( sret > 0 )
{
ret = sret;
}
else
{
ret = 0; // no data;
}
}
else if ( retval == 0 ) // timeout
{
ret = 0;
}
else // error
{
ret = -1;
}
return ret;
}
SX_S32 Bit_Server_Send1(PT_CLIENT handle, void *buf, SX_S32 len)
{
if( handle == NULL || len <= 0 || len > UDP_MAX_LEN )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_S32 length;
if( buf )
{
length = MIN(len, UDP_MAX_LEN);
return sendto( handle->sockfd, (const SX_S8 *)buf, length, 0, (struct sockaddr *)&(handle->cliaddr2), sizeof(handle->cliaddr2) );
}
else
{
length = MIN(handle->s32SendLen, UDP_MAX_LEN);
return sendto( handle->sockfd, handle->pszSendBuf, length, 0, (struct sockaddr *)&(handle->cliaddr2), sizeof(handle->cliaddr2) );
}
}
SX_S32 Cfg_Server_Send2(PT_CLIENT handle, void *buf, SX_S32 len)
{
if( handle == NULL || len <= 0 || len > UDP_MAX_LEN )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_S32 length;
if( buf )
{
length = MIN(len, UDP_MAX_LEN);
return sendto( handle->sockfd, (const SX_S8 *)buf, length, 0, (struct sockaddr *)&(handle->cliaddr2), sizeof(handle->cliaddr2) );
}
else
{
length = MIN(handle->s32SendLen, UDP_MAX_LEN);
return sendto( handle->sockfd, handle->pszSendBuf, length, 0, (struct sockaddr *)&(handle->cliaddr2), sizeof(handle->cliaddr2) );
}
}
#endif
3、视频数据流上报
提供上报和接收的api
发送
//unicast send 192.168.0.163 /or boardcast send 192.168.0.255 /or mutilcast send 224.1.1.1
static SX_S32 MEDIUM_UDP_Open( void *handle, SX_S8 *dstIp0, SX_S16 dstPort0, SX_S8 *dstIp1, SX_S16 dstPort1 )
{
SX_U8 ttl = 64;
struct in_addr iaddr;
PT_Medium ptTmp = (PT_Medium)handle;
if( ptTmp == NULL )
return -1;
ptTmp->fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_IP );
if( ptTmp->fd <= 0 )
{
TRACE( DL_WARNING, "open udp failed\n" );
goto cleanup;
}
#if 1
ptTmp->other[0].sin_family = AF_INET;
inet_pton(AF_INET, dstIp0, &ptTmp->other[0].sin_addr);
ptTmp->other[0].sin_port = htons(dstPort0);
if(MEDIUM_MAX_CH > 1)
{
ptTmp->other[1].sin_family = AF_INET;
inet_pton(AF_INET, dstIp1, &ptTmp->other[1].sin_addr);
ptTmp->other[1].sin_port = htons(dstPort1);
}
#endif
#if 0 //get default sendbuf size 160k
int opt_val1=0,opt_val2=0;
socklen_t opt_len = sizeof(opt_val1);
getsockopt(ptTmp->fd, SOL_SOCKET, SO_SNDBUF, &opt_val1,&opt_len);
getsockopt(ptTmp->fd, SOL_SOCKET, SO_RCVBUF, &opt_val2,&opt_len);
while(1)
{
printf("SNDBUF = %dk RCVBUF = %dk \r\n", opt_val1 / 1024, opt_val2 / 1024);
}
#endif
#if 0
int nSendBufLen = 50*1024; //set sendbuf size 160k
setsockopt(ptTmp->fd, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBufLen, sizeof(int));
nSendBufLen = 160*1024; //set sendbuf size 160k
setsockopt(ptTmp->fd, SOL_SOCKET, SO_RCVBUF, ( const char* )&nSendBufLen, sizeof(int));
#endif
#if 0 //only need send frame
ptTmp->me.sin_family = AF_INET;
ptTmp->me.sin_port = htons(0);
ptTmp->me.sin_addr.s_addr = INADDR_ANY;
if( bind(ptTmp->fd, (struct sockaddr *)&ptTmp->me, sizeof(struct sockaddr_in) ) < 0 )
{
TRACE( DL_WARNING, "bind udp failed\n" );
goto cleanup;
}
iaddr.s_addr = INADDR_ANY;
setsockopt(ptTmp->fd, IPPROTO_UDP, IP_MULTICAST_IF, &iaddr, sizeof(struct in_addr)); // Set the outgoing interface to DEFAULT
setsockopt(ptTmp->fd, IPPROTO_UDP, IP_MULTICAST_TTL, &ttl, sizeof(SX_U8)); // Set multicast packet TTL to 10; default TTL is 1
//setsockopt(ptTmp->fd, IPPROTO_UDP, IP_MULTICAST_LOOP, &loop, sizeof(SX_U8)); // send multicast traffic to myself too
#endif
ptTmp->fdGPIO = open("/dev/pio_in", O_RDWR);
#if 0
SX_U8 sendbuf[1400];
memset(sendbuf,0x55,1400);
int i = 0;
for(i =0; i< 30;i++)
{
if( sendto(ptTmp->fd,
&sendbuf,
1400, //headlen + datalen + crclen,
0,
(struct sockaddr *)&ptTmp->other[0],
sizeof(struct sockaddr_in)) < 0 )
printf( "+++ udp send fail ++++\r\n" );
else
printf( "+++ udp send succes ++++\r\n" );
}
#endif
return 0;
cleanup:
if( ptTmp->fd)
{
shutdown( ptTmp->fd, SHUT_RDWR );
close( ptTmp->fd );
ptTmp->fd = 0;
}
return -1;
}
void Frame_Sender_Close( PT_Sender handle )
{
if( handle )
{
MEDIUM_Destroy("UDP");
xine_free( handle->ps8FrameBuff );
pthread_mutex_destroy( &handle->mutex );
handle->_is = NULL;
xine_freep( (void *)&handle );
}
}
static HI_VOID* Frame_Sender_ThreadCenter(HI_VOID* p)
{
PT_Sender handle = (PT_Sender)p;
while (HI_TRUE == handle->bThreadStart)
{
if( !handle->bVideoReady )
{
handle->bVideoReady = Frame_Sender_ReceiveVideo( handle );
}
}
handle->bThreadStart = HI_FALSE;
return NULL;
#endif
}
HI_S32 Frame_Sender_Start( PT_Sender handle )
{
handle->bThreadStart = HI_TRUE;
return pthread_create(&(handle->threadId), 0, Frame_Sender_ThreadCenter, (HI_VOID*)handle);
}
HI_S32 Frame_Sender_Stop( PT_Sender handle )
{
if ( HI_TRUE == handle->bThreadStart )
{
handle->bThreadStart = HI_FALSE;
if (handle->threadId)
{
pthread_join( handle->threadId, 0 );
handle->threadId = 0;
}
}
return HI_SUCCESS;
}
接收
PT_Receiver Frame_Receiver_Open(PT_Top is,const SX_S8 *recv_ip, SX_S16 recv_port, SX_S8 * dev_name)
{
if( is == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return NULL;
}
PT_Receiver handle = (PT_Receiver)xine_xmalloc(sizeof(T_Receiver));
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return NULL;
}
handle->_is = is;
handle->ptFrameQueue = handle->_is->ptFrameQueue;
handle->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(handle->sockfd < 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
Frame_Receiver_Close(handle);
return NULL;
}
SX_S32 mode = 0;
if( -1 == ioctl(handle->sockfd, FIONBIO, &mode) ) //for nonblock
{
TRACE(DL_ERROR, "DL_ERROR\n");
Frame_Receiver_Close(handle);
return NULL;
}
memset( &(handle->servaddr), 0, sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
SX_S8 ip[20] = {0};
strcpy( ip, recv_ip );
#if 1
handle->servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#else
if( inet_pton( AF_INET, ip, &(handle->servaddr.sin_addr) ) <= 0)
{
TRACE(DL_ERROR, "DL_ERROR\n");
SERVER_Close(handle);
return NULL;
}
/*
bzero( &(handle->servaddr), sizeof(handle->servaddr));
handle->servaddr.sin_family = AF_INET;
//inet_pton(AF_INET, send_ip, &(handle->servaddr.sin_addr));
handle->servaddr.sin_addr.s_addr = inet_addr(ip);
*/
#endif
handle->servaddr.sin_port = htons(recv_port);
if( bind(handle->sockfd, (struct sockaddr *)&(handle->servaddr), sizeof(handle->servaddr)) < 0 )
{
TRACE(DL_ERROR, "DL_ERROR\n");
close(handle->sockfd);
Frame_Receiver_Close(handle);
return NULL;
}
SX_S32 address[4] = {0, 0, 0, 0};
if( 4 == sscanf( (SX_S8 *)ip, "%d.%d.%d.%d", &address[0], &address[1], &address[2], &address[3] ) )
{
if( (address[0] >= 224) && (address[0] <= 239) )
{
if( !join_multicast_group(handle->sockfd, ip, recv_port, dev_name) )
{
TRACE(DL_WARNING, "join_multicast_group failed \n");
}
}
}
#if 0 //get default sendbuf size 160k
int opt_val1=0,opt_val2=0;
socklen_t opt_len = sizeof(opt_val1);
getsockopt(handle->sockfd, SOL_SOCKET, SO_SNDBUF, &opt_val1,&opt_len);
getsockopt(handle->sockfd, SOL_SOCKET, SO_RCVBUF, &opt_val2,&opt_len);
while(1)
{
printf("SNDBUF = %dk RCVBUF = %dk \r\n", opt_val1 / 1024, opt_val2 / 1024);
}
#endif
#if 0
int nSendBufLen = 50*1024; //set sendbuf size 160k
setsockopt(handle->sockfd, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBufLen, sizeof(int));
nSendBufLen = 160*1024; //set sendbuf size 160k
setsockopt(handle->sockfd, SOL_SOCKET, SO_RCVBUF, ( const char* )&nSendBufLen, sizeof(int));
#endif
//int loop=0; //Off
//setsockopt( handle->sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop) );
#if 0 //test
SX_U8 sendbuf[1400];
memset(sendbuf,0x55,1400);
int i = 0;
for(i =0; i< 30;i++)
{
if( sendto(handle->sockfd,
&sendbuf,
1400, //headlen + datalen + crclen,
0,
(struct sockaddr *)&(handle->servaddr),
sizeof(handle->servaddr)) < 0 )
printf( "+++ udp send fail ++++\r\n" );
else
printf( "+++ udp send succes ++++\r\n" );
}
#endif
handle->cliaddr_len = sizeof(handle->cliaddr);
handle->pszRecvBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszRecvBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Frame_Receiver_Close(handle);
return NULL;
}
handle->pszSendBuf = (SX_S8 *)xine_xmalloc( UDP_MAX_LEN );
if( handle->pszSendBuf == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
Frame_Receiver_Close(handle);
return NULL;
}
TRACE(DL_INFO, "ip:%s, port:%d, dev:%s\n", recv_ip, recv_port, dev_name);
return handle;
}
//static SX_U32 cnt = 0;
SX_S32 Frame_Receiver_Rcv(PT_Receiver handle, void *buf, SX_S32 timeoutMs )
{
if( handle == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
return 0;
}
SX_U8 *pDst = NULL;
SX_S32 ret, sret, retval;
SX_S64 max_fd;
fd_set readfds;
struct timeval tv;
int i = 0;
FD_ZERO(&readfds);
FD_SET( handle->sockfd, &readfds );
max_fd = handle->sockfd;
tv.tv_sec = timeoutMs/1000;
tv.tv_usec = (timeoutMs%1000)*1000;
retval = select( max_fd + 1, &readfds, NULL, NULL, &tv );
if ( retval > 0 )
{
//printf("++++ decoder Server Receive data ++++\r\n");
if( buf ){
sret = recvfrom( handle->sockfd, (SX_S8 *)buf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr), &(handle->cliaddr_len) );
}
else{
sret = recvfrom( handle->sockfd, handle->pszRecvBuf, UDP_MAX_LEN, 0, (struct sockaddr *)&(handle->cliaddr), &(handle->cliaddr_len) );
handle->s32RecvLen = sret;
}
if ( sret > 0 )
{
ret = sret;
pDst = (SX_U8 *)&handle->FrameSendQueue.data;
memcpy( (SX_S8 *)pDst, (SX_S8 *)buf,sret);
//printf("+ recvfrom %ld +\r\n",sret);
if(handle->ptFrameQueue == NULL || &(handle->FrameSendQueue) == NULL)
return -1;
QUEUE_Frame_Send(handle->ptFrameQueue,&(handle->FrameSendQueue));
//cnt ++;
//tset
//QUEUE_Frame_Receive(handle->ptFrameQueue,&(handle->FrameRcvQueue),1);
//for(i = 0; i< sret;i++)
//printf("%x",handle->FrameRcvQueue.data[i]);
//printf("\r\n");
}
else
{
ret = 0; // no data;
}
}
else if ( retval == 0 )
{
// timeout
ret = 0;
}
else
{
// error
ret = -1;
}
return ret;
}
static HI_VOID* Frame_Receiver_ThreadCenter(HI_VOID* p)
{
PT_Receiver handle = (PT_Receiver)p;
// static SX_U32 oldts = 0;
//static SX_U32 newts = 0;
// oldts = get_sys_ms();
while(handle->bThreadStart != HI_FAILURE)
{
SX_S32 len = Frame_Receiver_Rcv(handle, handle->pszRecvBuf, 3);
if(len < 0)
delay_ms(1);
//newts = get_sys_ms();
//if(newts - oldts > 1000)
//{
//printf("++++++++++ Frame_Receive %dms get cnt %d +++++++\r\n",newts - oldts,cnt);
//cnt = 0;
//oldts = newts;
//}
}
}
void Frame_Receiver_Close( PT_Receiver handle )
{
if( handle )
{
xine_free( handle->pszRecvBuf);
pthread_mutex_destroy( &handle->mutex );
handle->_is = NULL;
xine_freep( (void *)&handle );
}
}
HI_S32 Frame_Receiver_Start( PT_Receiver handle )
{
handle->bThreadStart = HI_TRUE;
return pthread_create(&(handle->threadId), 0, Frame_Receiver_ThreadCenter, (HI_VOID*)handle);
}
HI_S32 Frame_Receiver_Stop( PT_Receiver handle )
{
if ( HI_TRUE == handle->bThreadStart )
{
handle->bThreadStart = HI_FALSE;
if (handle->threadId)
{
pthread_join( handle->threadId, 0 );
handle->threadId = 0;
}
}
return HI_SUCCESS;
}
接收头文件
typedef struct Receiver
{
volatile HI_BOOL bThreadStart;
pthread_t threadId;
pthread_mutex_t mutex;
HI_S8 * ps8FrameBuff;
PT_Top _is;
SX_S64 sockfd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
socklen_t cliaddr_len;
SX_S32 s32RecvLen;
SX_S8 * pszRecvBuf;
SX_S32 s32SendLen;
SX_S8 * pszSendBuf;
} T_Receiver, *PT_Receiver;
发送头文件
#define MAX_FRAME_LEN (200*1024)
typedef struct Sender
{
volatile HI_BOOL bThreadStart;
pthread_t threadId;
pthread_mutex_t mutex;
SX_S32 fd;
struct sockaddr_in other[MEDIUM_MAX_CH];
struct sockaddr_in me;
HI_S8 * ps8FrameBuff;
PT_Top _is;
} T_Sender, *PT_Sender;
配置头文件
typedef struct SERVER{
volatile HI_BOOL bThreadStart;
pthread_t threadId;
pthread_mutex_t mutex;
SX_S64 sockfd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
socklen_t cliaddr_len;
SX_S32 s32RecvLen;
SX_S8 * pszRecvBuf;
SX_S32 s32SendLen;
SX_S8 * pszSendBuf;
}T_SERVER, *PT_SERVER;
typedef struct Config
{
PT_Top _is;
PT_SERVER ptServerCmd; //net address
SX_S8 strMac[32]; // '\0' end
SX_S8 strIP[32]; // '\0' end
SX_S8 strNetMask[32]; // '\0' end
SX_S8 strGatWay[32]; // '\0' end
SX_U16 u16LocalPort;
//
SX_S8 szMac[6];
SX_S8 szIP[4];
SX_S8 szNetMask[4];
SX_S8 szGatWay[4];
//
SX_S8 strStreamIP[32]; // '\0' end
SX_U16 u16StreamPort;
SX_S8 szStreamIP[4];
//
SX_U32 u32IP;
SX_U32 u32StreamIP;
} T_Config, *PT_Config;
bit头文件
typedef struct CLIENT{
SX_S64 sockfd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr1;
struct sockaddr_in cliaddr2;
socklen_t servaddr_len;
socklen_t cliaddr_len2;
socklen_t cliaddr_len1;
SX_S32 s32SendLen;
SX_S8 * pszSendBuf;
SX_S32 s32RecvLen;
SX_S8 * pszRecvBuf;
}T_CLIENT, *PT_CLIENT;
main函数
static SX_S32 TOP_SendBIT_1( PT_Top handle ) //when rcv client pc request , passive send data to client pc
{
SX_S32 ret = 0;
static SX_U16 u16packnum = 1;
//PT_Config cfg = (PT_Config)(handle->hConfig);
memset(handle->ptClientBIT1->pszSendBuf,0,UDP_MAX_LEN);
PT_DataPkt_1 pkt = (PT_DataPkt_1)(handle->ptClientBIT1->pszSendBuf);
pkt->u32Sync = PKT_SYNC;
pkt->u8Cmd = CMD_ACK_BIT1;
pkt->u32DataLen = sizeof(T_BIT_1);
pkt->u32totalPktNum = 1;
pkt->u32currretPkt = 1;
pkt->CRC32 = 0xC4C3C2C1;
//file data
memset((SX_U8 *)(&pkt->BITData), 0, sizeof(T_BIT_1) );
pkt->BITData.u8head = 12;
pkt->BITData.u8SoftwareRev = (SX_U8)software_reversion;
pkt->BITData.u8reserv0 = 0;
pkt->BITData.u8reserv1 = 0;
pkt->BITData.u8devicetype = (SX_U8)U8DeviceType;
pkt->BITData.u8devicestatus = (SX_U8)client_fpga_status;
pkt->BITData.u16packnum = u16packnum;
memset( pkt->BITData.u8reserver2, 0, sizeof(pkt->BITData.u8reserver2) );
ret = Bit_Server_Send1(handle->ptClientBIT1, (SX_S8 *)pkt, sizeof(T_DataPkt_1));
u16packnum ++;
if( u16packnum > 65535)
u16packnum = 0;
return ret;
}
SX_S32 Wait_ReadBTI_Writecofg( PT_Top handle )
{
if(handle == NULL)
return -1;
memset(handle->ptClientBIT1->pszRecvBuf,0,UDP_MAX_LEN);
SX_S32 len = Bit_Server_Receive1(handle->ptClientBIT1, handle->ptClientBIT1->pszRecvBuf, 1 );
if( (len > 0) && (len <= UDP_MAX_LEN) )
{
//TRACE( DL_INFO, "CLIENT_Receive:%d\n", len );
PT_ReadBITDataPkt ptbitdata= (PT_ReadBITDataPkt)handle->ptClientBIT1->pszRecvBuf;
if( ptbitdata->u32Sync != PKT_SYNC || (ptbitdata->u8Cmd != CMD_READ_BIT1 && ptbitdata->u8Cmd != CMD_WRITE_CONFIG))
{
return -1;
}
else
{
if(ptbitdata->u8Cmd == CMD_READ_BIT1 )
{
u8Cmd =CMD_READ_BIT1;
TRACE( DL_INFO, "CMD_READ_BIT1:%d\n", len );
}
if(ptbitdata->u8Cmd == CMD_WRITE_CONFIG)
{
u8Cmd =CMD_WRITE_CONFIG;
TRACE( DL_INFO, "CMD_WRITE_CONFIG:%d\n", len );
}
return len;
}
}
else
{
return -1;
}
}
static HI_S32 TOP_Start( PT_Top handle )
{
pthread_mutex_init( &handle->mutex, NULL );
handle->hSenderFrame = (void *)Frame_Sender_Open( handle, ((PT_Config)handle->hConfig)->strStreamIP, ((PT_Config)handle->hConfig)->u16StreamPort, ((PT_Config)handle->hConfig)->strStreamIP, ((PT_Config)handle->hConfig)->u16StreamPort);
handle->hReceiverFrame = (void *)Frame_Receiver_Open( handle,((PT_Config)handle->hConfig)->strIP, ((PT_Config)handle->hConfig)->u16LocalPort, "eth0");
Frame_Sender_Start( (PT_Sender)(handle->hSenderFrame) );
Frame_Receiver_Start( (PT_Receiver)(handle->hReceiverFrame) );
//ClientBIT1
handle->ptClientBIT1 = Bit_Server_Open1(((PT_Config)handle->hConfig)->strIP, UDP_PORT_BIT1,"224.1.1.4", UDP_PORT_BIT1, "eth0");
if( handle->ptClientBIT1 == NULL )
{
TRACE(DL_ERROR, "DL_ERROR\n");
s32Ret |= 1;
}
printf( "TOP_Start OK !\n" );
return s32Ret;
}
#define DefaultLocMac "00:00:23:34:45:66"
#define DefaultLocIp "192.168.0.163"
#define DefaultLocNetMask "255.255.255.0"
#define DefaultLocGatWay "192.168.0.1"
#define DefaultLocPort 10001
#define DefaultStreamIp "224.1.1.1"
#define DefaultStreamPort 8080
int main(int argc, char *argv[])
{
HI_S32 s32Ret = 0;
SX_U32 ts0 = get_sys_ms();
SX_U32 oldMs = ts0;
SX_U32 currentMs = ts0;
g_bQuit = SX_FALSE;
// local Default net address
sprintf( handle->strMac , DefaultLocMac);
sprintf( handle->strIP , DefaultLocIp);
sprintf( handle->strNetMask , DefaultLocNetMask);
sprintf( handle->strGatWay , DefaultLocGatWay);
handle->u16LocalPort = DefaultLocPort;
handle->u32IP = inet_addr(handle->strIP);
SX_S8 szMac[6] ={0x00,0x00,0x23,0x34,0x45,0x66};
SX_S8 szIP[4] ={192,168,0,163};
SX_S8 szNetMask[4] ={255,255,255,0};
SX_S8 szGatWay[4] ={192,168,0,1};
memcpy(handle->szMac,szMac,sizeof(szMac));
memcpy(handle->szIP,szIP,sizeof(szIP));
memcpy(handle->szNetMask,szNetMask,sizeof(szNetMask));
memcpy(handle->szGatWay,szGatWay,sizeof(szGatWay));
// dest stream net address
sprintf( handle->strStreamIP, DefaultStreamIp);//"224.1.1.1"
handle->u32StreamIP = inet_addr(handle->strStreamIP);
handle->u16StreamPort = UDP_PORT_SATA; //10004
SX_S8 szStreamIP[4] ={224,1,1,1};
memcpy(handle->szStreamIP,szStreamIP,sizeof(szStreamIP));
printf("mac:%s, ip:%s, u16LocalPort:%d, mask:%s, gateway:%s, ip:%s, streamPort:%d\n",
handle->strMac,
handle->strIP,
handle->u16LocalPort,
handle->strNetMask,
handle->strGatWay,
handle->strStreamIP,
handle->u16StreamPort
);
handle->ptServerCmd = Cfg_Server_Open( handle->strIP, UDP_PORT_CFG, "eth0");
if( handle->ptServerCmd == NULL )
{
TRACE(DL_ERROR, "Cfg_Server_Open :%s, %d failed!\n", handle->strIP, UDP_PORT_CFG);
CONFIG_Close( handle );
}
while( g_bQuit == SX_FALSE)
{
s32Ret = TOP_Start( is );
if (HI_SUCCESS != s32Ret)
{
TRACE( DL_ERROR, "error\n" );
}
while( g_bQuit == SX_FALSE )
{
// 1. send BIT
currentMs = get_sys_ms();
if( MYFABS(currentMs, oldMs) > 1000 )
{
oldMs = currentMs;
TOP_SendBIT_2( is );
SX_S32 second = MYFABS(currentMs, ts0) / 1000;
if( second % 60 == 0 )
{
//TRACE( DL_INFO, "system run %ld hour %ld minutes\n", second/3600, (second%3600 ) / 60 );
}
// 2. update config
SX_S32 ret = 0;
ret = CONFIG_Update( is->hConfig );
if( ret & UPDATE_NET_ADDR)
{
ret &= ( ~UPDATE_NET_ADDR );
break;
}
ret = Wait_ReadBTI_Writecofg(is);
if( ret > 0 && u8Cmd == CMD_READ_BIT1 )
{
TOP_SendBIT_1(is);
}
else if( ret > 0 && u8Cmd == CMD_WRITE_CONFIG )
{
PT_CofDataPkt2 ptConfigRcv= (PT_CofDataPkt2)is->ptClientBIT1->pszRecvBuf;
ret = CONFIG_CollectConfigData2( is->hConfig, ptConfigRcv);
}
if( ret > 0 && u8Cmd == CMD_WRITE_CONFIG)// client cfg our system success ,reboot system
{
break;
}
}
TOP_Stop( is );
}
TRACE(DL_INFO, "exit main ok\n");
return 0;
}
//思想:
每秒主动发送bit至本qt
循环轮询监视客户app发送的读bit,和配置信息。
循环监视本qt下发的读写命令。
本代码只实现组播,广播的逻辑,具体业务逻辑,未暴露,如若他人复制,只可参考。