公司机房到阿里云的数据传输有时候会出现丢包,所以需要程序来进行查询和排查,公司前辈写了一个程序来进行机器之间的丢包统计。
服务器:pong.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXLINE 1500
#define SERV_PORT 2019 //服务器端口号
void do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)
{
int n, jzq_num = 0;
socklen_t len;
char mesg[MAXLINE];
int i ;
for(;;)
{
len = clilen;
/* waiting for receive data */
n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
mesg[n]=0;
printf("recvfrom data:%d %d\n",n, ++jzq_num);
printf("%s\n",mesg);
/* sent data back to client */
sendto(sockfd, mesg, n, 0, pcliaddr, len);
}
}
int main(int argc,char *argv[])
{
int sockfd;
int m_port = SERV_PORT;
int result, buf_len;
int len = sizeof (buf_len);
struct sockaddr_in servaddr, cliaddr;
if (argc >=2) sscanf(argv[1],"%d",&m_port);
sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */
/* init servaddr */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(m_port);
printf("port:%d\n", m_port);
result = getsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, (socklen_t *)&len);
printf ("one:getsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);
if(result == 0 && buf_len < 1024*1024)
{
buf_len = 1024*1024;
setsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, len); //接收缓冲区大小为1MB
printf ("setsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);
result = getsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, (socklen_t *)&len);
printf ("two:getsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);
}
/* bind address and port to socket */
if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
{
perror("bind error");
exit(1);
}
printf("UPD servese is bind success and do_echo now\n");
do_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
return 0;
}
测试程序check.cpp
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/time.h>
#define MAXSIZE 1024
#define FDSIZE 1024
#define EPOLLEVENTS 20
#define SERV_PORT (9999)//你需要连接的服务器端口号
#define LOCAL_PORT (0) //UDP传输端口,0表示系统分配
#define WAIT_TIME (100)
static int handle_connection(int sockfd, struct sockaddr_in *servaddr, int flag);
static int handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf, struct sockaddr_in *servaddr);
static int do_read(int epollfd,int fd,int sockfd,char *buf, struct sockaddr_in *servaddr);
static void add_event(int epollfd,int fd,int state);
static void delete_event(int epollfd,int fd,int state);
static void modify_event(int epollfd,int fd,int state);
char send_buf[MAXSIZE];
char ip[50];
int check(char *ip, int port, int flag)
{
int sockfd;
struct sockaddr_in servaddr;
struct sockaddr_in clientaddr;
int res ;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
servaddr.sin_addr.s_addr = inet_addr(ip);
bzero(&clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(LOCAL_PORT);
clientaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd, (struct sockaddr *)&clientaddr, sizeof(clientaddr)) == -1)
{
perror("bind error");
exit(1);
}
sockaddr_in addrMy;
memset(&addrMy,0,sizeof(addrMy));
int leng = sizeof(addrMy);
if (getsockname(sockfd, (sockaddr*)&addrMy, (socklen_t*)&leng) != 0)
{
puts("Getsockname Error!");
return 0;
}
printf("Current Socket PORT->%d ",ntohs(addrMy.sin_port));
fflush(stdout);
res = handle_connection(sockfd, &servaddr, flag);
close(sockfd);
return res;
}
void print_cur_time()
{
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep); //取得当地时间
printf ("%d-%02d-%02d %02d:%02d:%02d ",(1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
fflush(stdout);
}
int main(int argc,char *argv[])
{
FILE *fp;
int num = 0, lost_num = 0;
while(1)
{
fp = fopen("./home/jzq/Check/poxy.txt*/", "r");//自己创目录文件,poxy.txt里是要连的ip地址
if(fp == NULL)
{
printf("The poxy.txt not exit\n");
return 0;
}
while(~fscanf(fp, "%s", ip))
{
print_cur_time();
printf("ALY -> %s ", ip);
fflush(stdout);
check(ip, SERV_PORT, 2);
sleep(0.1);
}
fclose(fp);
}
return 0;
}
static int handle_connection(int sockfd, struct sockaddr_in *servaddr, int flag)
{
int epollfd;
struct epoll_event events[EPOLLEVENTS];
int ret, len, num = 30;
int lost_num =0;
epollfd = epoll_create(FDSIZE);
add_event(epollfd,sockfd,EPOLLIN);
while(num--)
{
len = 20; //包长,可以按需要增大,但要注意传输时间要相应增大
memset(send_buf, '6', len);
send_buf[len] = 0;
if(sendto(sockfd, send_buf, len, 0, (struct sockaddr*)servaddr, sizeof(struct sockaddr_in)) <= 0)
{
printf("sendto error");
continue;
}
ret = epoll_wait(epollfd, events, epollevents, wait_time);
if(ret > 0 && (len = handle_events(epollfd, events, ret, sockfd, send_buf, servaddr)) > 0)
{
if(!len)
printf("unkonw\n");
}
else
{
lost_num++;
printf(".");
fflush(stdout);
}
}
close(epollfd);
printf("lost:%d%\n", lost_num*100/30);
return lost_num;
}
static int handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf, struct sockaddr_in *servaddr)
{
int fd;
int i;
for (i = 0;i < num;i++)
{
fd = events[i].data.fd;
if ((events[i].events & EPOLLIN) && (fd == sockfd))
return do_read(epollfd,fd,sockfd,buf, servaddr);
}
return -1;
}
static int do_read(int epollfd,int fd,int sockfd,char *buf, struct sockaddr_in *servaddr)
{
socklen_t len = sizeof(struct sockaddr_in);
return recvfrom(sockfd, buf, MAXSIZE, MSG_DONTWAIT, (struct sockaddr *)servaddr, &len);
}
static void add_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev);
}
static void delete_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev);
}
static void modify_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev);
}