멀티캐스트 송수신 속도 재기
송신 프로그램에서 수신 프로그램으로 멀티캐스트 전송.
걸리는 시간은 평균 60.605 * 10-6 초.
리눅스 커널 : 2.6.32
CPU : Intel(R) Xeon(R) CPU E5640 @ 2.67GHz x 16코어
NIC : 10G (같은 서버 안에서 처리되는거라서 NIC를 거치진않음)
===
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include "Util.h"
#include <sys/types.h> /* for type definitions */
#include <sys/socket.h> /* for socket API calls */
#include <netinet/in.h> /* for address structs */
#include <arpa/inet.h> /* for sockaddr_in */
#include <stdio.h> /* for printf() and fprintf() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for strlen() */
#include <unistd.h> /* for close() */
#define MAX_LEN 1024 /* maximum receive string size */
#define MIN_PORT 1024 /* minimum port allowed */
#define MAX_PORT 65535 /* maximum port allowed */
long g_total_recv_count = 0;
double g_total_diff = 0;
struct timespec tp;
int
main(int argc, char *argv[])
{
int sock; /* socket descriptor */
int flag_on = 1; /* socket option flag */
struct sockaddr_in mc_addr; /* socket address structure */
char recv_str[MAX_LEN+1]; /* buffer to receive string */
int recv_len; /* length of string received */
struct ip_mreq mc_req; /* multicast request structure */
char* mc_addr_str; /* multicast IP address */
// unsigned short mc_port; /* multicast port */
int mc_port; /* multicast port */
struct sockaddr_in from_addr; /* packet source */
unsigned int from_len; /* source addr length */
/* validate number of arguments */
if (argc != 3)
{
fprintf(stderr,
"Usage: %s <Multicast IP> <Multicast Port>\n",
argv[0]);
exit(1);
}
mc_addr_str = argv[1]; /* arg 1: multicast ip address */
mc_port = atoi(argv[2]); /* arg 2: multicast port number */
/* validate the port range */
if ((mc_port < MIN_PORT) || (mc_port > MAX_PORT))
{
fprintf(stderr, "Invalid port number argument %d.\n",
mc_port);
fprintf(stderr, "Valid range is between %d and %d.\n",
MIN_PORT, MAX_PORT);
exit(1);
}
/* create socket to join multicast group on */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
perror("socket() failed");
exit(1);
}
/* set reuse port to on to allow multiple binds per host */
if ((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag_on,
sizeof(flag_on))) < 0) {
perror("setsockopt() failed");
exit(1);
}
/* construct a multicast address structure */
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
mc_addr.sin_port = htons(mc_port);
/* bind to multicast address to socket */
if ((bind(sock, (struct sockaddr *) &mc_addr,
sizeof(mc_addr))) < 0)
{
perror("bind() failed");
exit(1);
}
/* construct an IGMP join request structure */
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
/* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void*) &mc_req, sizeof(mc_req))) < 0)
{
perror("setsockopt() failed");
exit(1);
}
for (;;)
{
memset(recv_str, 0, sizeof(recv_str));
from_len = sizeof(from_addr);
memset(&from_addr, 0, from_len);
if ((recv_len = recvfrom(sock, recv_str, MAX_LEN, 0,
(struct sockaddr*)&from_addr, &from_len)) < 0)
{
perror("recvfrom() failed");
exit(1);
}
////////////
clock_gettime( CLOCK_REALTIME, &tp );
recv_str [recv_len] = 0;
long u1 = atol( &recv_str[11] );
recv_str[10] = 0x00;
long h1 = atol( &recv_str[0] );
long diff = tp.tv_nsec - u1;
// printf( "%10ld.%09ld <- %10ld.%09ld. diff(%ld)\n", tp.tv_sec, tp.tv_nsec, h1, u1, diff );
if( diff < 1000*1000 && diff > 0 )
{
g_total_recv_count++;
g_total_diff += diff;
}
if( g_total_recv_count >= 10 )
{
printf( "%06ld.%06ld : %03.3f micro sec (per %ld packets) Received %d bytes from %s\n",
lGetHHMMSS(), lGetUSEC(),
g_total_recv_count,
g_total_diff/g_total_recv_count/1000,
recv_len, inet_ntoa(from_addr.sin_addr) );
g_total_recv_count = 0;
g_total_diff = 0;
sleep( 1 );
}
}
/* send a DROP MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(void*) &mc_req, sizeof(mc_req))) < 0)
{
perror("setsockopt() failed");
exit(1);
}
close(sock);
}
// endoffile : mcreceive.cpp
===