代码1:服务器端
#include "common.h"
int main()
{
int fd;
struct sockaddr_in caddr;
char recvbuf[1024];
char sendbuf[1024];
int set = 1;
int i=0;
int addrLen = sizeof(caddr);
//接收数据
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1){
printf("socket fail\n");
return 0;
}
setsockopt(fd, SOL_SOCKET,SO_REUSEADDR, &set, sizeof(int));
memset(&caddr, 0, sizeof(struct sockaddr_in));
caddr.sin_family = AF_INET;
caddr.sin_port = htons(8080);
caddr.sin_addr.s_addr = INADDR_ANY;
// 必须绑定,否则无法监听
if(bind(fd, (struct sockaddr *)&caddr, sizeof(struct sockaddr)) == -1){
printf("bind fail\n");
return 0;
}
while(1)
{
int recvbytes = recvfrom(fd, recvbuf, 1024, 0,(struct sockaddr *)&caddr, &addrLen);
printf("recv:%s\n",recvbuf);
i++;
//if(i==2)break;
}
printf("please input ...\n");
scanf("%s",sendbuf);
sendto(fd,sendbuf, 1024, 0,(struct sockaddr *)&caddr, sizeof(struct sockaddr));
}
代码2:客户端
#include "common.h"
int main()
{
int fd;
int optval = 1;//这个值一定要设置,否则可能导致sendto()失败
struct sockaddr_in saddr;
int sendBytes;
char sendbuf[1024];
char recvbuf[1024];
int addrLen = sizeof(saddr);
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
printf("socket fail\n");
return ;
}
setsockopt(fd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));//允许发送广播数据包,允许重用本地地址
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(8080);
while(1)
{
printf("please input ...\n");
scanf("%s",sendbuf);
if((sendBytes = sendto(fd, sendbuf, 1024, 0,(struct sockaddr *)&saddr, sizeof(struct sockaddr))) == -1)
{
printf("sendto model fail, errno=%d\n", errno);
return ;
}
printf("send meg success...\n\n");
}
/*while(1)
{
recvfrom(fd, recvbuf, 1024, 0,(struct sockaddr *)&saddr, &addrLen);
printf("recvbuf:%s\n",recvbuf);
}*/
}
结果:
如果把客户端的127.0.0.1改为255.255.255.255,结果为:
广播成功,所有的服务器均能收到
组播:
服务器端:
#include "common.h"
int fd;
struct sockaddr_in caddr,recvaddr;
int addrLen ;
void *thread(void *argv)
{
char recvbuf[1024];
while(1)
{
recvfrom(fd, recvbuf, 1024, 0,(struct sockaddr *)&recvaddr, &addrLen);
printf("recv:%s\n",recvbuf);
}
}
int main()
{
char sendbuf[1024];
int set = 1;
int i=0;
addrLen = sizeof(caddr);
int sendBytes;
//接收数据
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1){
printf("socket fail\n");
return 0;
}
memset(&caddr, 0, sizeof(struct sockaddr_in));
memset(&recvaddr, 0, sizeof(struct sockaddr_in));
caddr.sin_family = AF_INET;
caddr.sin_port = htons(8080);
caddr.sin_addr.s_addr = INADDR_ANY;
// 绑定监听
if(bind(fd, (struct sockaddr *)&caddr, sizeof(struct sockaddr)) == -1)
{
printf("bind fail\n");
return 0;
}
int loop = 1;
/*去掉以下4行,将不会收到客户端消息(移出了多播组)*/
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.88");//多播地址
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(struct ip_mreq));//加入多播组
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR, &set, sizeof(int));//端口复用
setsockopt(fd,IPPROTO_IP, IP_MULTICAST_LOOP, &loop,sizeof (loop));//允许环回
pthread_t pthid;
pthread_create(&pthid, NULL, thread, NULL);
while(1)
{
printf("input ... \n");
scanf("%s",sendbuf);
if((sendBytes = sendto(fd, sendbuf, 1024, 0,(struct sockaddr *)&recvaddr, sizeof(struct sockaddr))) == -1)//发送给客户端
{
printf("sendto model fail, errno=%d\n", errno);
return ;
}
}
}
客户端:
#include "common.h"
int fd;
struct sockaddr_in sendaddr,recvaddr;
int addrLen;
void *thread(void *argv)
{
char recvbuf[1024];
while(1)
{
printf("------------------\n");
int ret = recvfrom(fd, recvbuf, 1024, 0,(struct sockaddr *)&recvaddr, &addrLen);
if(ret<0)
{
perror("recvfrom");
return 0;
}
printf("recv:%s\n",recvbuf);
}
}
int main()
{
addrLen = sizeof(sendaddr);
int optval = 1;
int sendBytes;
char sendbuf[1024];
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
printf("socket fail\n");
return ;
}
memset(&sendaddr, 0, sizeof(struct sockaddr_in));
memset(&recvaddr, 0, sizeof(struct sockaddr_in));
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR, &optval, sizeof(int));
sendaddr.sin_family = AF_INET;
sendaddr.sin_addr.s_addr = inet_addr("224.0.0.88"); //指定发送的多播组
sendaddr.sin_port = htons(8080); //指定发送到哪个端口
pthread_t pthid;
pthread_create(&pthid, NULL, thread, NULL);
while(1)
{
printf("please input ...\n");
scanf("%s",sendbuf);
if((sendBytes = sendto(fd, sendbuf, 1024, 0,(struct sockaddr *)&sendaddr, sizeof(struct sockaddr))) == -1)
{
printf("sendto model fail, errno=%d\n", errno);
return 0;
}
//printf("send meg success...\n\n");
}
}
结果不再展示
mark:
setsockopt(fd, SOL_SOCKET,SO_REUSEADDR, &set, sizeof(int));
设置端口复用要在socket之后紧跟。在bind之后再设置没作用,仍会出现bind失败的情况。
创建套接字中的PF_INET实际也可换为AF_INET,暂且不清楚两者区别。