#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <pthread.h>
// Unix下UDP广播群聊例程
// 编译: gcc group_talk.c -lpthread
#define BROCAST_PORT 6024
//#define RECEIVE_PORT 6024
#define THREAD_RUNNING 1
#define THREAD_STOP 0
int brocast_sock = -1;
int receive_sock = -1;
int thrd_status = THREAD_RUNNING;
pthread_t thread_id;
struct msg_t
{
unsigned int msg_id;
struct in_addr src_ip;
struct in_addr dst_ip;
char nename[128];
char message[1024];
};
char conn_agent_ip[128];
char init_agent_ip[128];
char find_agent_ip[128];
#define AGENT_PORT 6024
char local_device_name[128] = "eth0";
char local_device_ip[128] = "";
char local_nename[128] = "";
char old_device_ip[128] = "";
#define SA struct sockaddr
#define LISTENQ 5
#define MAX_IFS 64
char * get_device_ip(char * device_name)
{
struct ifreq *ifr, *ifend;
struct ifreq ifreq;
struct ifconf ifc;
struct ifreq ifs[MAX_IFS];
static char ip_addr[128];
int SockFD;
SockFD = socket(AF_INET, SOCK_DGRAM, 0);
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0) {
printf("ioctl(SIOCGIFCONF): %m\n");
close(SockFD);
return NULL;
}
ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
if (ifr->ifr_addr.sa_family == AF_INET) {
strncpy(ifreq.ifr_name, ifr->ifr_name,sizeof(ifreq.ifr_name));
if (ioctl (SockFD, SIOCGIFHWADDR, &ifreq) < 0) {
printf("SIOCGIFHWADDR(%s): %m\n", ifreq.ifr_name);
close(SockFD);
return NULL;
}
printf("Device %s \n", ifreq.ifr_name);
if (strcmp(device_name, ifreq.ifr_name)==0)
{
printf("Get [%s] IP [%s]\n", device_name, inet_ntoa( ( (struct sockaddr_in *) &ifr->ifr_addr)->sin_addr));
sprintf(ip_addr, "%s", inet_ntoa( ( (struct sockaddr_in *) &ifr->ifr_addr)->sin_addr));
close(SockFD);
return ip_addr;
}
}
}
close(SockFD);
memset(ip_addr, 0, sizeof(ip_addr));
return ip_addr;
}
int brocast_msg(char * msg, int msg_len)
{
// printf("brocast_msg(len:%d)\n", msg_len);
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family=AF_INET;
addrto.sin_addr.s_addr=htonl(INADDR_BROADCAST);
addrto.sin_port=htons(BROCAST_PORT);
int ret;
int len = sizeof(struct sockaddr_in);
int i;
ret=sendto(brocast_sock, msg, msg_len, 0, (struct sockaddr*)&addrto, len);
if(ret<0)
{
printf("brocast_msg: send error[%d]\n", ret);
return -1;
}
else
{
// printf("brocast_msg: sent message OK\n");
}
return 0;
}
int hello()
{
printf("hello()\n");
struct msg_t msg;
msg.msg_id = 1;
inet_pton(AF_INET, local_device_ip, (void *)&msg.src_ip);
inet_pton(AF_INET, "0.0.0.0" , (void *)&msg.dst_ip);
snprintf(msg.nename, sizeof(msg.nename), "%s", local_nename);
snprintf(msg.message, sizeof(msg.message), "hello.");
brocast_msg((char *)&msg, sizeof(msg));
return 0;
}
int goodbye()
{
struct msg_t msg;
msg.msg_id = 1;
inet_pton(AF_INET, local_device_ip, (void *)&msg.src_ip);
inet_pton(AF_INET, "0.0.0.0" , (void *)&msg.dst_ip);
snprintf(msg.nename, sizeof(msg.nename), "%s", local_nename);
snprintf(msg.message, sizeof(msg.message), "goodbye.");
brocast_msg((char *)&msg, sizeof(msg));
return 0;
}
void *thrd_receive_msg(void *arg)
{
// 设置其他线程可以cancel掉此线程
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
int len = sizeof(struct sockaddr_in);
struct msg_t rec_msg;
while(thrd_status == THREAD_RUNNING)
{
int ret;
struct sockaddr_in from;
bzero(&from, sizeof(struct sockaddr_in));
from.sin_family = AF_INET;
from.sin_addr.s_addr = htonl(INADDR_ANY);
from.sin_port = htons(BROCAST_PORT);
fd_set fdsr;//文件描述符集
int sel;
struct timeval tv;
FD_ZERO(&fdsr);
FD_SET(receive_sock, &fdsr);//加入描述符集
tv.tv_sec = 1;
tv.tv_usec = 0;
sel = select(receive_sock + 1, &fdsr, NULL, NULL, &tv);
if (sel < 0) {
printf("_recv_from: select error![%d:%s]\n", errno, strerror(errno));
//continue;
}
else if (sel == 0)
{
// printf("recv_from: time out![%d:%s]\n", errno, strerror(errno));
}
else
{
bzero(&rec_msg, sizeof(rec_msg));
ret=recvfrom(receive_sock, &rec_msg, sizeof(rec_msg), 0, (struct sockaddr*)&from,(socklen_t*)&len);
if(ret<=0)
{
printf("read error....\n");
}
else
{
if (rec_msg.msg_id == 0)
{
inet_ntop(AF_INET, (void *)&rec_msg.src_ip, find_agent_ip, 16);
printf("main: Find agent ip=[%s].\n", find_agent_ip);
}
else if(rec_msg.msg_id == 1)
{
char src_ip[128],dst_ip[128];
inet_ntop(AF_INET, (void *)&rec_msg.src_ip, src_ip, 16);
inet_ntop(AF_INET, (void *)&rec_msg.dst_ip, dst_ip, 16);
if (strcmp(src_ip, local_device_ip))
printf("%s: %s\n", rec_msg.nename, rec_msg.message);
}
}
}
sleep(1);
}
printf("Thread is exiting.\n");
pthread_exit(NULL);
}
void signal_handler(int sig)
{
// printf("signal_handler()\n");
thrd_status = THREAD_STOP;
goodbye();
close(brocast_sock);
close(receive_sock);
exit(0);
return;
}
int init(int argc, char * argv[])
{
// 解析参数
if (argc == 3)
{
sprintf(local_nename, "%s", argv[1]);
sprintf(local_device_name, argv[2]);
}
else if (argc == 2)
{
sprintf(local_nename, "%s", argv[1]);
sprintf(local_device_name, "eth0");
}
else
{
sprintf(local_device_name, "eth0");
sprintf(local_nename, "%s", get_device_ip(local_device_name));
}
sprintf(local_device_ip, "%s", get_device_ip(local_device_name));
printf("!\n");
if (strlen(local_device_ip) < 1)
{
printf("get device ip error!\n", local_device_name);
exit(0);
}
printf("init: nename[%s] device name = [%s] device ip = [%s]\n", local_nename, local_device_name, local_device_ip);
// 设置信号
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
// 设置网络
// 绑定地址
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family = AF_INET;
addrto.sin_addr.s_addr = htonl(INADDR_ANY);
addrto.sin_port = htons(BROCAST_PORT);
if ((receive_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("init: socket error\n");
exit(0);
}
const int opt = 1;
//设置该套接字为广播类型,
int nb = 0;
nb = setsockopt(receive_sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
if(nb == -1)
{
printf("init: set socket error...\n");
close(receive_sock);
exit(0);
}
if(bind(receive_sock,(struct sockaddr *)&(addrto), sizeof(struct sockaddr_in)) == -1)
{
printf("init: bind error...\n");
close(receive_sock);
exit(0);
}
if ((brocast_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("socket error\n");
exit(0);
}
//设置该套接字为广播类型,
nb = setsockopt(brocast_sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
if(nb == -1)
{
printf("set socket error...\n");
close(brocast_sock);
exit(0);
}
// 创建线程,每个线程号返回给thread,每个线程的入口函数均为thrd_brocast_ip
if (pthread_create(&thread_id,NULL,thrd_receive_msg,NULL)!=0)
{
printf("Create thread error!\n");
exit(0);
}
else
{
printf("Create thread success!\n");
}
printf("init: Init complete!\n");
}
int main( int argc, char ** argv)
{
init(argc, argv);
if (hello())
{
printf("hello fail!\n");
return -1;
}
char buf[2048];
int len;
struct msg_t brc_msg;
while(thrd_status == THREAD_RUNNING)
{
bzero((void *)buf, sizeof(buf));
scanf("%s", buf);
len = strlen(buf);
if (len >= 1024)
{
printf("message too long\n");
continue;
}
brc_msg.msg_id = 1;
inet_pton(AF_INET, local_device_ip, (void *)&brc_msg.src_ip);
inet_pton(AF_INET, "0.0.0.0" , (void *)&brc_msg.dst_ip);
snprintf(brc_msg.nename, sizeof(brc_msg.nename), "%s", local_nename);
snprintf(brc_msg.message, sizeof(brc_msg.message), "%s", buf);
brocast_msg((char *)&brc_msg, sizeof(brc_msg));
}
printf("Program is exiting.\n");
close(brocast_sock);
close(receive_sock);
return 0;
}
转载于:https://my.oschina.net/u/1264314/blog/160980