UDP通信流程
描述
UDP没有所谓的服务器与客户端,只需双方绑定对方的Ip和端口号即可。
步骤
一、先初始化本地以及对方IP以及端口号
char hostIp[32];
char localIp[32];
int hostport;
int localport;
本地IP及端口号设置
1. struct sockaddr_in Mcast_addr;
2.bzero(&localIp[0],32);
3.sprintf(localIp,"192.168.2.200",);
4.localport = 50001;
5.Mcast_addr.sin_family = AF_INET;
6.Mcast_addr.sin_addr.s_addr = inet_addr(localIp); //本地端口号
7.Mcast_addr.sin_port = htons(localport); //本地IP
对方IP及端口号设置
1.struct sockaddr_in Host_addr;
2.bzero(&hostIp[0],32);
3.sprintf(hostIp,"192.168.2.200",);
4.hostport = 40001;
5.Host_addr.sin_family = AF_INET;
6.Host_addr.sin_addr.s_addr = inet_addr(hostIp); //对方端口号
7.Host_addr.sin_port = htons(hostport); //对方IP
二、建立连接
if ( (socketfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
perror("建立失败\r\n");
return ;
}
else
{
printf("建立成功\r\n");
//绑定端口号,否则本地每次对外发送一次数据,端口号就会随机改变
bind(socketfd, (struct sockaddr *)&Mcast_addr, sizeof(Mcast_addr));
}
三、发送数据(本地)
temp_buf
所要发送的数据缓冲区
addrlen
sizeof(Host_addr)
Host_addr
对方IP地址
sendnum
发送的数据长度
sendto(socketfd,temp_buf,sendnum,0,(struct sockaddr*)&Host_addr,addrlen);
四、接收数据(本地)
fd_set readskt;
FD_ZERO(&readskt);
FD_SET(socketfd,&readskt);
ret = select(socketfd+1,&readskt,NULL,NULL,&time_out);
if(ret > 0)
{
RecvLen = recvfrom(socketfd, RecvBuf, MAXDATASIZE, 0,NULL,NULL);
}
整体流程
void Cnetwork::initial(portcfg_t * hostportinfo)
{
//将组播地址加入到路由表
system("route add -net 224.1.0.1 netmask 255.255.255.255 eth1");
}
void Cnetwork:: GetData()
{
char RecvBuf[MAXDATASIZE];
int i,numbytes;
int RecvLen = 0;
int ret,retUDPgroup,retUDPsingle=0;
int maxfd;
int addr_len;
fd_set readskt,readsktUDPgroup,readsktUDPsingle;
struct timeval time_out;
FD_ZERO(&readsktUDPsingle);
FD_ZERO(&readsktUDPgroup);
time_out.tv_sec =0;
time_out.tv_usec = 400000;
FD_SET(socketfd_udp_single,&readsktUDPsingle);
FD_SET(mcastsocketfd,&readsktUDPgroup);
ret = 0;
retUDPsingle = select(socketfd_udp_single+1,&readskt,NULL,NULL,&time_out);
retUDPgroup = select(mcastsocketfd+1,&readsktUDPgroup,NULL,NULL,&time_out);
if (( ret > 0)||( retUDPgroup > 0)||(retUDPsingle>0) )
{
if((netmode == 0)&&( ret > 0))
{
RecvLen = recv(socketfd, RecvBuf,MAXDATASIZE,0);
}
else
{
if(retUDPsingle>0)
{
printf("UDP接收到单播数据\r\n");
RecvLen = recvfrom(socketfd_udp_single, RecvBuf, MAXDATASIZE, 0,NULL,NULL);
}
else if(retUDPgroup>0)
{
printf("UDP接收到多播数据\r\n");
addr_len = sizeof(Local_addr);
RecvLen = recvfrom(mcastsocketfd, RecvBuf, MAXDATASIZE, 0,(struct sockaddr*)&Local_addr,(socklen_t*)&addr_len);
}
}
if ( RecvLen > 0 )
{
time_t tp;
struct tm * lt;
time(&tp);
lt=localtime(&tp);
printf("\r\n");
printf("net udp receive time= %d年%d月%d日%d时%d分%d秒\r\n",(lt->tm_year-100+2000),(lt->tm_mon+1),lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec);
printf("recv byte = %d \r\n",RecvLen);
printf("receive: ");
for ( i = 0; i < RecvLen; i++ )
{
printf("%2.2X ",(unsigned char)RecvBuf[i]);
}
printf("\n\n");
for ( i = 0; i < RecvLen; i++ )
{
putdata(&HostInfo->sendtoapp_dataque, RecvBuf[i]);
}
}
else if ( RecvLen == 0 )
{
printf("recv_len = 0\n");
CloseConnect();
}
else
{
if ( errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN )
{
}
else
{
printf("recv_len < 0\n");
CloseConnect();
}
}
timeout_num = 0;
}
}
void Cnetwork::SendData()
{
char temp_buf[MAXDATASIZE];
int i,sendnum;
int addrlen;
if ( (sendnum = HostInfo->recfromapp_dataque.count) > 0 )
{
for ( i = 0; i < sendnum; i++ )
{
temp_buf[i] = HostInfo->recfromapp_dataque.buf[mod(HostInfo->recfromapp_dataque.start+i,HostInfo->recfromapp_dataque.size)];
}
}
if ( sendnum > 0 )
{
if(netmode == 1)
{
addrlen = sizeof(Host_addr);
if ( (sendnum = HostInfo->recfromapp_dataque.count) > 0 )
{
time_t tp;
struct tm * lt;
time(&tp);
lt=localtime(&tp);
printf("\r\n");
printf("net send time= %d年%d月%d日%d时%d分%d秒\r\n",(lt->tm_year-100+2000),(lt->tm_mon+1),lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec);
printf("need byte = %d \r\n",sendnum);
for ( i = 0; i < sendnum; i++ )
{
temp_buf[i] = HostInfo->recfromapp_dataque.buf[mod(HostInfo->recfromapp_dataque.start+i,HostInfo->recfromapp_dataque.size)];
printf("%2.2X ",(unsigned char)temp_buf[i]);
}
printf("\r\n");
}
int sendlen = sendto(socketfd_udp_single ,temp_buf,sendnum,0,(struct sockaddr*)&Host_addr,addrlen);//mark
for ( i = 0; i < sendnum; i++ )
{
dropdata(&HostInfo->recfromapp_dataque);
}
}
}
}
void Cnetwork::CreatConnect()
{
char McastIp[32];
char localIp[32];
char hostIp[32];
printf("CreatConnect enter \r\n");
if ( socketfd == -1 ) //100128-jxy
{
printf("netmode = %d\r\n",netmode);
//创建UDP单播套接字
if(netmode == 1)//UDP
{
if ( (socketfd_udp_single = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
perror("Error connecting to socket\n");
return ;
}
else
{
printf("<<<<<<<<<Net Mode UDP>>>>>>>>>\r\n");
bind(socketfd_udp_single, (struct sockaddr *)&Local_addr, sizeof(Local_addr)); //绑定端口号,否则本机端口号一直改变
}
}
}
//多播配置
if(mcastsocketfd == -1)
{
if(netmode== 1)//UDP
{
if ( (mcastsocketfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
printf("Error connecting to mcastsocketfd\n");
perror("Error connecting to mcastsocketfd\n");
return ;
}
else
{
printf("<<<<<<<<<Net Mode UDP zubo>>>>>>>>>\r\n");
int yes = 1;
if(setsockopt(mcastsocketfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))<0)
{
printf("reusing ADDR failed\r\n");
}
memset(McastIp,0,32);
sprintf(McastIp,"224.1.0.1");
//初始化本地地址
memset(&Local_addr, 0, sizeof(Local_addr));
Local_addr.sin_family = AF_INET;
Local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
Local_addr.sin_port = htons(2000);
//绑定socket
int err = bind(mcastsocketfd,(struct sockaddr*)&Local_addr, sizeof(Local_addr)) ;
if(err < 0)
{
printf("bind()");
perror("bind()");
exit(1);
}
int loop = 1;
err = setsockopt(mcastsocketfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
if(err<0)
{
printf("setsockeopt():IP_MULTICAST_LOOP\r\n");
}
//将本机加入多播组
struct ip_mreq mreq;
memset (&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr(McastIp);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
err = setsockopt(mcastsocketfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
if(err<0)
{
perror("setsockopt():IP_ADD_MEMBERSHIP");
printf("setsockeopt():IP_ADD_MEMBERSHIP,err = %d\r\n",err);
}
}
}
}
}