UDP组播通讯可用
功能:
实现两台设备通过同一组播地址进行信息交互.
机器A 机器B
机器A发送指令,机器B接收指令 机器B回复一条报文 机器A 接收一条报文
机器A为发送方,客户端
机器B为接收端服务器端
发送端
Bind本地端口与IP,向组里发送数据,从本地接收数据。记得setsockopt加组与reuseaddr
机器B代码:
/*
*本功能只能实现一对一的组播通讯,
*若要实现一对多通讯,需对发送代码进行简单修改
*本人已经试过一对多的,至于一对几可以根据心跳包个数,即几个人像里面
*发送心跳包,更改很简单,就不详细说了
*
*
*
*/
/代码块/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFLEN 255
```
static int count = 0;
static struct itimerval oldtv;
void set_timer(int sec, int usec)
{
struct itimerval itv;
itv.it_interval.tv_sec = sec;
itv.it_interval.tv_usec = usec;
itv.it_value.tv_sec = sec;
itv.it_value.tv_usec = usec;
setitimer(ITIMER_REAL, &itv, &oldtv);
}
void signal_handler(int m)
{
count++;
//printf("%d\n", count);
}
int main(int argc, char **argv)
{
struct sockaddr_in peeraddr, myaddr;
printf("in main\n");
int sockfd;
char recmsg[BUFLEN + 1];
unsigned int socklen;
signal(SIGALRM, signal_handler);
set_timer(3,0);
/* 创建 socket 用于UDP通讯 */
sockfd = socket(AF_INET, SOCK_DGRAM,0);
if (sockfd < 0) {
printf("socket creating error\n");
exit(1);
}
socklen = sizeof(struct sockaddr_in);
/* 设置对方的端口和IP信息 */
memset(&peeraddr, 0, socklen);
peeraddr.sin_family = AF_INET;
peeraddr.sin_port = htons(8888);
peeraddr.sin_addr.s_addr=inet_addr("224.1.1.12");
int iOptionValue = 1;
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr=inet_addr("224.1.1.12");//组播地址
mreq.imr_interface.s_addr=inet_addr("192.168.142.128");//发送端mreq的interface为本地地址
/* 设置自己的端口和IP信息 */
memset(&myaddr, 0, socklen);
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8686);
myaddr.sin_addr.s_addr = inet_addr("192.168.142.128");
int opt=1;
int yes = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
//close(m_socket);
perror("setsockopt");
//return -2;
}
//参数loop设置为0禁止回送,设置为1允许回送
int Loop = 1;
//if (! LoopBack) Loop = 0;
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&Loop, sizeof(int)) < 0)
{
perror("setsockopt:IP_MULTICAST_LOOP");
//return -4;
}
//将socket
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1)
{
perror("setsockopt");
exit(-1);
}
/* 绑定自己的端口和IP信息到socket上 */
if (bind(sockfd, (struct sockaddr *) &myaddr,sizeof(struct sockaddr_in)) == -1)
{
perror("Bind error\n");
exit(0);
}
char buf[128]={0};
/* 循环接受用户输入的消息发送组播消息 */
int k=0;
for (;;)
{
/* 接受用户输入 */
printf("请输入:\n");
bzero(recmsg, BUFLEN + 1);
if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF)
exit(0);
/* 发送消息 */
if (sendto(sockfd,recmsg, sizeof(recmsg), 0,(struct sockaddr *) &peeraddr, sizeof(struct sockaddr_in)) < 0)
{
printf("sendto error!\n");
}
else
{
int t=0;
printf("begin recv\n");
int n = recvfrom(sockfd, buf,sizeof(buf), 0,
(struct sockaddr *) &myaddr, &socklen); //
if(n>0)
{
printf("发送端接收成功recv ok buf is %s\n",buf);
count=0;
}
#include "g_recv.h"
int main(int argc, char **argv)
{
int k=udp_group_recv("224.1.1.12",8888);
}
机器A的代码:
#include "g_recv.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFLEN 255
int n1=0;
static int count = 0;
static struct itimerval oldtv;
void set_timer(int sec, int usec)
{
struct itimerval itv;
itv.it_interval.tv_sec = sec;
itv.it_interval.tv_usec = usec;
itv.it_value.tv_sec = sec;
itv.it_value.tv_usec = usec;
setitimer(ITIMER_REAL, &itv, &oldtv);
}
void signal_handler(int m)
{
count ++;
if(n1>=1 && count>2)
{
//system("cd /root/Desktop/group; ./send");
}
//printf("%d\n", count);
}
```
int udp_group_recv(char *group_ip,int group_port)
{
/* 设置发送组播消息的源主机的地址信息 */
struct sockaddr_in peeraddr,myaddr;
struct in_addr ia;
int sockfd;
char recv[300];
unsigned int socklen,n;
struct hostent *group;
struct ip_mreq mreq;
signal(SIGALRM, signal_handler);
set_timer(2,0);
socklen=sizeof(struct sockaddr_in);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&peeraddr,0, socklen);
//组播地址设置
peeraddr.sin_family = AF_INET;
peeraddr.sin_addr.s_addr=inet_addr(group_ip);
peeraddr.sin_port = htons(group_port);
/* 设置发送组播消息的源主机的地址信息 */
mreq.imr_multiaddr.s_addr=inet_addr(group_ip);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1)
{
perror("setsockopt");
exit(-1);
}
// if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(8888);
myaddr.sin_addr.s_addr=INADDR_ANY;//recv端为INADDR——ANY
int opt=1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
perror("setsockopt REUSE");
exit(-1);
}
int yes = 1;
/* allow multiple sockets to use the same PORT number */
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
//close(m_socket);
perror("setsockopt");
//return -2;
}
int rcvbuf_len;
socklen_t len = sizeof(rcvbuf_len);
rcvbuf_len = 200 * 1024 * 512;//100M
len = sizeof(rcvbuf_len);
//int e = EBADF;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, (void *) &rcvbuf_len, len) < 0)
{
perror("setsockopt");
}
/*
*/
//参数loop设置为0禁止回送,设置为1允许回送
int Loop = 0;
//if (! LoopBack) Loop = 0;
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&Loop, sizeof(int)) < 0)
{
perror("setsockopt:IP_MULTICAST_LOOP");
//return -4;
}
if (bind(sockfd, (struct sockaddr *) &peeraddr, sizeof(struct sockaddr_in)) == -1)
{
printf("Bind error\n");
}
char buf[128]={0};
//pthread_create(&pd,NULL,go,);
/* 循环接收网络上来的组播消息 */
for (;;)
{
printf("n1 is %d\n",n1);
n = recvfrom(sockfd, buf,sizeof(buf), 0, (struct sockaddr *) &peeraddr, &socklen);
if (n < 0)
{
printf("recvfrom err in udptalk!\n");
exit(4);
}
else
{
count=0;
n1++;
printf("peer:%s\n", buf);
int k=0;
printf("请输入:\n");
bzero(recv, sizeof(recv));
if (fgets(recv, sizeof(recv), stdin) == (char *) EOF)
exit(0);
L: n=sendto(sockfd, recv,sizeof(recv), 0,(struct sockaddr *) &peeraddr, socklen);
if(n>0)
{
printf("recv 端发送成功\n");
}
}
}
return 0;
}
希望大家多提宝贵意见谢谢。