#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include<errno.h>
#include<sys/time.h>
#define BUF_LEN 16
#define OPTION_STRING "i:p:n:v:w:r:c:l:h:a:d:b:q:z"
#define SET0_BIT(value, bit) ((value)&=~(1<<(bit)))
#define SET1_BIT(value, bit) ((value)|= (1<<(bit)))
#define GET_BIT(value, bit) ((value)&(1<<(bit)))
#define CPL_BIT(value, bit) ((value)^=(1<<(bit)))
static int sock_fd = -1;
extern char **environ;
static char *smp_sys_argv_last = NULL;
static char *smp_sys_env_last = NULL;
struct par_val {
/*clean write read*/
char mode;
/*latency switch*/
char lat_sw;
/*latency value*/
char lat_val;
/*loss packet switch*/
char packet_loss_sw;
/*loss packet rate value*/
char packet_loss_rate;
char read_loss_val;
short int read_curr_03_loss_rate_num;
short int read_curr_1_loss_rate_num;
short int read_curr_2_loss_rate_num;
short int read_curr_5_loss_rate_num;
short int read_curr_10_loss_rate_num;
};
static void
sigint(int signal_num)
{
if(sock_fd > 0) {
close(sock_fd);
}
exit(-1);
}
static void
udp_send(int fd, int packet_num,
struct sockaddr *dst, struct par_val val)
{
int index, ret, flag;
socklen_t len = sizeof(*dst);
flag = val.mode;
char send_buf[BUF_LEN];
char recv_buf[BUF_LEN];
memset(send_buf, 0, BUF_LEN);
memcpy(send_buf, &val, sizeof(val));
for(index = 0; index < packet_num; index++) {
ret = sendto(fd, send_buf, sizeof(send_buf), 0, dst, len);
if(ret < 0) {
fprintf(stderr, "send error\n");
if(fd > 0)
close(fd);
exit(-1);
}
if(flag == 2) {
printf("--------------------receive data--------------------\n");
ret = recvfrom(fd, recv_buf, sizeof(recv_buf), 0, dst, &len);
if(ret > 0) {
struct par_val recv_val;
memcpy(&recv_val, recv_buf, sizeof(recv_buf));
fprintf(stdout, " current latency value = %d \n", (recv_val.read_loss_val - 48));
switch (val.packet_loss_rate) {
case 1:
fprintf(stdout, " current loss packet rate is %%0.3 \n");
fprintf(stdout, " current loss packet num = %d \n", recv_val.read_curr_03_loss_rate_num);
break;
case 10:
fprintf(stdout, " current loss packet rate is %%10 \n");
fprintf(stdout, " current loss packet num = %d \n", recv_val.read_curr_1_loss_rate_num);
break;
case 20:
fprintf(stdout, " current loss packet rate is %%20 \n");
fprintf(stdout, " current loss packet num = %d \n", recv_val.read_curr_2_loss_rate_num);
break;
case 50:
fprintf(stdout, " current loss packet rate is %%50 \n");
fprintf(stdout, " current loss packet num = %d \n", recv_val.read_curr_5_loss_rate_num);
break;
case 100:
fprintf(stdout, " current loss packet rate is %%100 \n");
fprintf(stdout, " current loss packet num = %d \n", recv_val.read_curr_10_loss_rate_num);
break;
default:
fprintf(stdout, "--------------------loss packet rate set error--------------------\n");
break;
}
} else {
fprintf(stdout, "--------------------recvive data error--------------------\n");
continue;
}
}
sleep(1);
}
}
static void
usage(void)
{
fprintf(stdout, "Usage:\n");
fprintf(stdout, "Option:\n");
fprintf(stdout, " -i, --<server ip> \n");
fprintf(stdout, " -p, --<server port> \n");
fprintf(stdout, " -n, --<packet num> \n");
fprintf(stdout, " -c, --<clean 0> \n");
fprintf(stdout, " -w, --<write 1> \n");
fprintf(stdout, " -r, --<read 2> \n");
fprintf(stdout, " -d, --<latency switch> \n");
fprintf(stdout, " -v, --<latency value -- 1:on, 0:off>\n");
fprintf(stdout, " -l, --<loss packet switch>\n");
fprintf(stdout, " -a, --<loss packet value -- 1:on, 0:off>\n");
fprintf(stdout, " byte(1) value, 0:clean, 1:write, 2:read \n");
fprintf(stdout, " byte(2) value, 0:latency off, 1:latency on \n");
fprintf(stdout, " byte(3) value, latency value, 1 <= value <= 10 \n");
fprintf(stdout, " byte(4) value, 0:loss packet off, 1:loss packet on \n");
fprintf(stdout, " byte(5) value, loss packet value, support parameter 1, 10, 20, 50, 100\n");
fprintf(stdout, " byte(6) value, read current latency value\n");
fprintf(stdout, " byte(7)-byte(8) read current 0.3%% loss packet, loss packet number \n");
fprintf(stdout, " byte(9)-byte(10) read current 1%% loss packet, loss packet number \n");
fprintf(stdout, " byte(11)-byte(12)read current 2%% loss packet, loss packet number \n");
fprintf(stdout, " byte(13)-byte(14)read current 5%% loss packet, loss packet number \n");
fprintf(stdout, " byte(15)-byte(16)read current 10%% loss packet, loss packet number \n");
return;
}
static u_char *
smp_strcpyn(u_char *dst, const u_char *src, size_t n)
{
if (n == 0)
return dst;
while (n--) {
*dst = *src;
if (*dst == '\0')
return dst;
dst++;
src++;
}
*dst = '\0';
return dst;
}
static int
smp_init_set_proc_title(int argc, char **argv)
{
int i = 0;
smp_sys_argv_last = argv[0];
for(i = 0; i < argc; i++) {
if (smp_sys_argv_last == argv[i]) {
smp_sys_argv_last = argv[i] + strlen(argv[i]) + 1;
}
}
smp_sys_env_last = smp_sys_argv_last;
for (i = 0; environ[i]; i++) {
if (smp_sys_env_last == environ[i]) {
smp_sys_env_last = environ[i] + strlen(environ[i]) + 1;
}
}
smp_sys_env_last--;
return 0;
}
static int
smp_cpy_environs(void)
{
u_char *new_addr = NULL;
size_t envsize = smp_sys_env_last - environ[0];
if ((new_addr = malloc(envsize)) == NULL)
return -1;
else {
u_char *current = new_addr;
u_char *p = current;
int i = 0;
for (i = 0; environ[i]; i++) {
current = smp_strcpyn(current, (u_char *) environ[i], strlen(environ[i]));
environ[i] = (char *)p;
current++;
p = current;
}
}
return 0;
}
static int
smp_reset_proc_titel(const u_char *title, size_t tlen, int argc, char **argv)
{
u_char *params = NULL;
if (argc <= 1) {
memset(argv[0], '\0', smp_sys_env_last - argv[0]);
memcpy(argv[0], title, tlen);
return 0;
} else {
u_char *current = NULL;
u_char *p = NULL;
size_t size = smp_sys_argv_last - argv[1];
int i = 0;
if ((params = malloc(size)) == NULL)
return 0;
current = params;
p = current;
for (i = 1; i < argc; i++) {
current = smp_strcpyn(current, (u_char *)argv[i], strlen(argv[i]));
argv[i] = (char *) p;
current++;
p = current;
}
memset(argv[0], '\0', smp_sys_env_last - argv[0]);
current = smp_strcpyn((u_char *)argv[0], title, tlen);
current++;
p = current;
for (i = 1; i < argc; i++) {
current = smp_strcpyn(current, (const u_char *)argv[i], strlen(argv[i]));
argv[i] = (char *)p;
current++;
p = current;
}
}
return 0;
}
static int
smp_set_proc_titel(const char *title, int argc, char **argv)
{
size_t tlen = 0;
if (title == NULL)
return -1;
tlen = strlen(title);
if (tlen <= strlen(argv[0])) {
for(int index = 0; index < argc; index++) {
memset(argv[index], '\0', strlen(argv[index]));
}
//memset(argv[0], '\0', strlen(argv[0]));
memcpy(argv[0], title, tlen);
return 0;
}
smp_init_set_proc_title(argc, argv);
smp_cpy_environs();
smp_reset_proc_titel((u_char *) title, tlen, argc, argv);
return 0;
}
int main(int argc, char **argv)
{
int argflag, packet_num = 1;
int latency, latency_val;
int loss_sw, loss_val, mode;
struct sockaddr_in cli_addr;
char *ser_ip = "127.0.0.1";
int ser_port = 8888;
struct sockaddr_in ser_addr;
struct par_val val;
/*Signal callback function*/
signal(SIGINT, sigint);
if(argc > 1) {
if(!strcmp(argv[1], "-s")) {
if(daemon(0, 0) == -1) {
fprintf(stdout, "daemon error\n");
exit(-1);
}
} else if(!strcmp(argv[1], "-h")) {
usage();
return 0;
}
}
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0) {
fprintf(stdout, "sock_fd open fail, ^^^^^^^^^^exit^^^^^^^^^^\n");
return -1;
}
memset(&ser_addr, 0, sizeof(ser_addr));
memset(&cli_addr, 0, sizeof(cli_addr));
memset(&val, 0, sizeof(val));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = inet_addr(ser_ip);
//ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ser_addr.sin_port = htons(ser_port);
while((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) {
switch (argflag) {
case 'i':
ser_ip = optarg;
ser_addr.sin_addr.s_addr = inet_addr(ser_ip);
break;
case 'p':
ser_port = atoi(optarg);
ser_addr.sin_port = htons(ser_port);
break;
case 'n':
packet_num = atoi(optarg);
break;
case 'c':
mode = atoi(optarg);
if(mode != 0) {
fprintf(stdout, "clean mode value set error\n");
goto failed;
}
memset(&val.mode, 0, sizeof(val.mode));
break;
case 'w':
mode = atoi(optarg);
if(mode != 1) {
fprintf(stdout, "write mode value set error\n");
goto failed;
}
SET1_BIT(val.mode, 0);
break;
case 'r':
mode = atoi(optarg);
if(mode != 2) {
fprintf(stdout, "read mode value set error\n");
goto failed;
}
SET1_BIT(val.mode, 1);
break;
case 'd':
latency = atoi(optarg);
if(latency == 0) {
memset(&val.lat_sw, 0, sizeof(val.lat_sw));
} else if(latency == 1) {
SET1_BIT(val.lat_sw, 0);
} else {
fprintf(stdout, "latency set error\n");
goto failed;
}
break;
case 'v':
latency_val = atoi(optarg);
if (latency_val == 1) {
SET1_BIT(val.lat_val, 0);
} else if(latency_val == 2) {
SET1_BIT(val.lat_val, 1);
} else if(latency_val == 3) {
SET1_BIT(val.lat_val, 0);
SET1_BIT(val.lat_val, 1);
} else if(latency_val == 4) {
SET1_BIT(val.lat_val, 2);
} else if(latency_val == 5) {
SET1_BIT(val.lat_val, 0);
SET1_BIT(val.lat_val, 2);
} else if(latency_val == 6) {
SET1_BIT(val.lat_val, 1);
SET1_BIT(val.lat_val, 2);
} else if(latency_val == 7) {
SET1_BIT(val.lat_val, 0);
SET1_BIT(val.lat_val, 1);
SET1_BIT(val.lat_val, 2);
} else if(latency_val == 8) {
SET1_BIT(val.lat_val, 3);
} else if(latency_val == 9) {
SET1_BIT(val.lat_val, 0);
SET1_BIT(val.lat_val, 3);
} else if(latency_val == 10) {
SET1_BIT(val.lat_val, 1);
SET1_BIT(val.lat_val, 3);
} else {
fprintf(stdout, "lat_val error\n");
goto failed;
}
break;
case 'l':
loss_sw = atoi(optarg);
if(loss_sw == 0) {
memset(&val.packet_loss_sw, 0, sizeof(val.packet_loss_sw));
} else if(loss_sw == 1) {
SET1_BIT(val.packet_loss_sw, 0);
} else {
fprintf(stdout, "loss switch set error\n");
goto failed;
}
break;
case 'a':
loss_val = atoi(optarg);
if(loss_val == 1) {
SET1_BIT(val.packet_loss_rate, 0);
} else if(loss_val == 10) {
SET1_BIT(val.packet_loss_rate, 1);
SET1_BIT(val.packet_loss_rate, 3);
} else if(loss_val == 20) {
SET1_BIT(val.packet_loss_rate, 2);
SET1_BIT(val.packet_loss_rate, 4);
} else if(loss_val == 50) {
SET1_BIT(val.packet_loss_rate, 1);
SET1_BIT(val.packet_loss_rate, 4);
SET1_BIT(val.packet_loss_rate, 5);
} else if(loss_val == 100) {
SET1_BIT(val.packet_loss_rate, 2);
SET1_BIT(val.packet_loss_rate, 6);
SET1_BIT(val.packet_loss_rate, 7);
} else {
fprintf(stdout, "loss value error\n");
goto failed;
}
break;
default:
break;
}
}
fprintf(stdout, " ip: %s \n", ser_ip);
fprintf(stdout, " port: %d \n", ser_port);
fprintf(stdout, " packet number %d \n", packet_num);
smp_set_proc_titel("lt-rdmatest", argc, argv);
udp_send(sock_fd, packet_num, (struct sockaddr *)&ser_addr, val);
close(sock_fd);
return 0;
failed:
usage();
close(sock_fd);
return -1;
}
.PHONY:clean
CFLAGS := -Wall -g
LDLIBS := -lpthread
APPS:= udp_send
all:${APPS}
install:
sudo mv ${APPS} /usr/bin
clean:
rm -rf ${APPS}
往一个ip发UDP的包,通过命令行配置参数,在data区域填充不同的参数。