/*
UDP MultiCast Echo Server
Author :Andrew Huang
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
static int listen_fd = -1;
void exit_handler(int no)
{
close(listen_fd);
exit(0);
}
/* 加入某个主播组 */
int add_multicast_group(int udp_fd,char * mgroup_ip)
{
struct ip_mreq multi_req;
multi_req.imr_multiaddr.s_addr = inet_addr(mgroup_ip);
multi_req.imr_interface.s_addr = htonl(INADDR_ANY);
if (-1 == setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multi_req,
sizeof(multi_req)))
{
perror("setsockopt_multi");
return -1;
}
return 0;
}
void * echo_thread(void * arg)
{
int client_fd = (int)arg;
int len;
char buffer[1024];
struct sockaddr_in local_addr;
struct sockaddr_in peer_addr;
socklen_t sockaddr_len = sizeof(struct sockaddr_in);
if(getsockname(client_fd,(struct sockaddr *)&local_addr,&sockaddr_len)!= 0)
{
perror("getsockname");
}
fprintf(stdout,"local addr %s:%d\n",inet_ntoa(local_addr.sin_addr),ntohs(local_addr.sin_port));
while(1)
{
len = recvfrom(client_fd,buffer,sizeof(buffer),0,(struct sockaddr *)&peer_addr,&sockaddr_len);
if(len <= 0)
goto EXIT_THREAD;
if(strncmp("exit",buffer,4)==0)
goto EXIT_THREAD;
sendto(client_fd,buffer,len,0,(struct sockaddr *)&peer_addr,sockaddr_len);
}
EXIT_THREAD:
fprintf(stdout,"thread %d exit\n",client_fd);
close(client_fd);
}
int main(int argc,char * argv[])
{
unsigned short port = 9000;
char buffer[1024];
char group_ip[64] ="224.0.0.1";
int len;
signal(SIGTERM,exit_handler);
signal(SIGINT,exit_handler);
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t sockaddr_len = sizeof(struct sockaddr_in);
if(argc > 1)
port = (unsigned short)atoi(argv[1]);
if(argc > 2)
strncpy(group_ip,argv[2],sizeof(group_ip)-1);
/* 第一步:创建UDP SOCKET*/
listen_fd = socket(PF_INET,SOCK_DGRAM,0);
if(listen_fd == -1)
{
perror("socket");
}
{
int reuse=1;
if(setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuse,sizeof(int))!= 0){
perror("setsockopt");
}
}
if(add_multicast_group(listen_fd,group_ip)!= 0)
{
perror("add_group");
exit(-1);
}
/* 第二步:设置侦听端口 */
server_addr.sin_family = AF_INET ; /* ipv4 */
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(listen_fd,(struct sockaddr *)&server_addr,sockaddr_len)!=0)
{
perror("bind");
exit_handler(0);
}
fprintf(stdout,"Multicase echo server ,listen on %d,fd%d,group %s\n",port,listen_fd,group_ip);
/* 第四步:开始用等待客户端的联接 */
echo_thread((void *)listen_fd);
fprintf(stdout,"close UDP server\n");
exit_handler(0);
}
|