广播服务器:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define SER_PORT 8888
#define SER_IP "0.0.0.0" //"0.0.0.0"
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("socket");
return -1;
}
printf("socket success __%d__\n", __LINE__);
//允许端口快速重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("setsockopt");
return -1;
}
printf("reuseaddr success __%d__\n", __LINE__);
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充服务器的地址信息结构体,给bind函数使用
//真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(port); //端口号的网络字节序,1024~49151
sin.sin_addr.s_addr = inet_addr(SER_IP); //本机IP的网络字节序,ifconfig查看本机IP
//127.0.0.1:本地换回IP,只能做本机通信的IP
//0.0.0.0 : 代表运行环境中所有可用IP
//绑定服务器自身的地址信息
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("bind");
return -1;
}
printf("bind success __%d__\n", __LINE__);
struct sockaddr_in cin; //存储发送方的地址信息
socklen_t addrlen = sizeof(cin);
char buf[128] = "";
ssize_t res = 0;
while(1)
{
bzero(buf, sizeof(buf)); //memset(buf, 0, sizeof(buf));
//接收数据,并将发送方的地址信息存储到cin结构体中
res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen);
// res = recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL); //不收发送方的地址信息
if(res < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("recvfrom");
return -1;
}
printf("[%s:%d] sfd=%d : %s __%d__\n",
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), sfd, buf, __LINE__);
}
//关闭
close(sfd);
return 0;
}
广播客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define SER_PORT 8888
#define SER_IP "192.168.124.255" //"0.0.0.0"
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("socket");
return -1;
}
printf("socket success __%d__\n", __LINE__);
//绑定客户端自身的地址信息,非必须绑定
//若不绑定,则IP是当前运行环境的IP, 端口是随机端口(49152~65535)
//设置广播
int broad = 1;
setsockopt(cfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad) );
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充地址信息结构体,给sendto函数使用,
//sendto想发给谁,就填谁的地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(port); //服务器绑定的端口号
sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器绑定的IP
struct sockaddr_in dstaddr; //存储发送方的地址信息
socklen_t addrlen = sizeof(dstaddr);
char buf[128] = "";
ssize_t res = 0;
while(1)
{
//从终端获取数据
printf("请输入>>> ");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = '\0';
if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("send");
return -1;
}
printf("sendto success __%d__\n", __LINE__);
}
//关闭
close(cfd);
return 0;
}
组播服务器:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define SER_PORT 8888
#define SER_IP "224.0.1.2" //"0.0.0.0"
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("socket");
return -1;
}
printf("socket success __%d__\n", __LINE__);
//允许端口快速重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("setsockopt");
return -1;
}
printf("reuseaddr success __%d__\n", __LINE__);
//加入多播组
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr(SER_IP);
mq.imr_address.s_addr = inet_addr("192.168.124.242");
mq.imr_ifindex = 0;
setsockopt( sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mq, sizeof(mq) );
printf("add membership [%s:%d] success__%d__\n",SER_IP, SER_PORT, __LINE__);
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充服务器的地址信息结构体,给bind函数使用
//真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(port); //端口号的网络字节序,1024~49151
sin.sin_addr.s_addr = inet_addr(SER_IP); //本机IP的网络字节序,ifconfig查看本机IP
//127.0.0.1:本地换回IP,只能做本机通信的IP
//0.0.0.0 : 代表运行环境中所有可用IP
//绑定服务器自身的地址信息
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("bind");
return -1;
}
printf("bind success __%d__\n", __LINE__);
struct sockaddr_in cin; //存储发送方的地址信息
socklen_t addrlen = sizeof(cin);
char buf[128] = "";
ssize_t res = 0;
while(1)
{
bzero(buf, sizeof(buf)); //memset(buf, 0, sizeof(buf));
//接收数据,并将发送方的地址信息存储到cin结构体中
res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen);
// res = recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL); //不收发送方的地址信息
if(res < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("recvfrom");
return -1;
}
printf("[%s:%d] sfd=%d : %s __%d__\n",
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), sfd, buf, __LINE__);
}
//关闭
close(sfd);
return 0;
}
组播客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define SER_PORT 8888
#define SER_IP "224.0.1.2" //"0.0.0.0"
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("socket");
return -1;
}
printf("socket success __%d__\n", __LINE__);
//绑定客户端自身的地址信息,非必须绑定
//若不绑定,则IP是当前运行环境的IP, 端口是随机端口(49152~65535)
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充地址信息结构体,给sendto函数使用,
//sendto想发给谁,就填谁的地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(port); //服务器绑定的端口号
sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器绑定的IP
struct sockaddr_in dstaddr; //存储发送方的地址信息
socklen_t addrlen = sizeof(dstaddr);
char buf[128] = "";
ssize_t res = 0;
while(1)
{
//从终端获取数据
printf("请输入>>> ");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = '\0';
if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "__%d__ ", __LINE__);
perror("send");
return -1;
}
printf("sendto success __%d__\n", __LINE__);
}
//关闭
close(cfd);
return 0;
}