PacketLossTestClient:
PacketLossTestClient.cpp:
// PacketLossTestClient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "SocketFrame.h"
int udp_client_fun_packetloss(int times, SOCKET s);
#define ECHOPORT "7210"
int main(int argc, char* argv[])
{
CSocketFrame frame;
int iResult;
SOCKET ClientSocket;
sockaddr_in servaddr;
int times;
//输入参数合法性检查
if (argc != 3)
{
printf("usage: PacketLossTestClient <IPaddress> <times>");
return -1;
}
//Windows Sockets Dll初始化
frame.start_up();
//创建客户端的数据报套接字,并与服务器建立连接
ClientSocket = frame.udp_client( ( char *)argv[1], ECHOPORT, true );
if ( ClientSocket == -1 )
return -1;
printf("客户端启动成功。\n");
//开始回射请求的发送与接收
//指明服务器的地址peer为用户输入的IP和端口号
if (frame.set_address( ( char *)argv[1], ECHOPORT, &servaddr, "udp" ) !=0 )
return 0;
times = atoi(argv[2]);
iResult = udp_client_fun_packetloss(times, ClientSocket );
if(iResult == -1)
printf("当前测试出错!\n");
frame.quit( ClientSocket );
return iResult;
}
/********************************************************
函数名:udp_client_fun_packetloss
输入参数:int times:发送次数
SOCKET s:客户端的数据报套接字
输出参数:0:成功,-1:失败
功能:丢包率测试客户端的具体功能函数
*********************************************************/
int udp_client_fun_packetloss(int times, SOCKET s)
{
int iResult, i =0;
char sendline[MAXLINE];
int recvtimes =0;
memset(sendline,1,MAXLINE);
//根据用户输入的发送次数循环发送相同的数据报
printf("\r\n客户端发送%d次数据\r\n", times);
while( i<times )
{
iResult = send(s,sendline,strlen(sendline),0 );
if(iResult == SOCKET_ERROR)
{
printf("send 函数调用错误,错误号: %ld\n", WSAGetLastError());
return -1;
}
i++;
}
return iResult;
}
SocketFrame.cpp:
#include "StdAfx.h"
#include "SocketFrame.h"
#include "ws2tcpip.h"
#include "mstcpip.h"
CSocketFrame::CSocketFrame(void)
{
}
CSocketFrame::~CSocketFrame(void)
{
}
/********************************************************
函数名:set_address
输入参数:char * hname:主机名 or 点分十进制表示的IP地址
char * sname:端口号
struct sockaddr_in * sap:以sockaddr_in结构存储的地址(输出参数)
char * protocol:字符串形式描述的协议类型,如"tcp"
输出参数:0表示成功,-1表示失败。
功能:根据给定的主机名或点分十进制表示的IP地址获得以sockaddr_in结构存储的地址
*********************************************************/
int CSocketFrame::set_address(char * hname, char * sname, struct sockaddr_in * sap, char * protocol)
{
struct servent *sp;
struct hostent *hp;
char *endptr;
unsigned short port;
unsigned long ulAddr = INADDR_NONE;
//对地址结构socketaddr_in初始化为0,并设置地址族为AF_INET
memset( sap,0, sizeof( *sap ) );
sap->sin_family = AF_INET;
if ( hname != NULL )
{
//如果hname不为空,假定给出的hname为点分十进制表示的数字地址,转换地址为sockaddr_in类型
ulAddr = inet_addr(hname);
if ( ulAddr == INADDR_NONE || ulAddr == INADDR_ANY) {
//printf("inet_addr 函数调用错误,错误号: %d\n", WSAGetLastError());
//调用错误,表明给出的是主机名,调用gethostbyname获得主机地址
hp = gethostbyname( hname );
if ( hp == NULL ) {
printf("未知的主机名,错误号: %d\n", WSAGetLastError());
return -1;
}
sap->sin_addr = *( struct in_addr * )hp->h_addr;
}
else
sap->sin_addr.S_un.S_addr=ulAddr;
}
else
//如果调用者没有指定一个主机名或地址,则设置地址为通配地址INADDR_ANY
sap->sin_addr.s_addr = htonl( INADDR_ANY );
//尝试转换sname为一个整数
port = (unsigned short )strtol( sname, &endptr, 0 );
if ( *endptr == '\0' )
{
//如果成功则转换为网络字节顺序
sap->sin_port = htons( port );
}
else
{
//如果失败,则假定是一个服务名称,通过调用getservbyname获得端口号
sp = getservbyname( sname, protocol );
if ( sp == NULL ) {
printf("未知的服务,错误号: %d\n", WSAGetLastError());
return -1;
}
sap->sin_port = sp->s_port;
}
return 0;
}
/********************************************************
函数名:start_up
输入参数:无
输出参数:0:成功,-1:失败
功能:初始化Windows Sockets DLL,协商版本号
*********************************************************/
int CSocketFrame::start_up(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int iResult;
// 使用 MAKEWORD(lowbyte, highbyte) 宏,在Windef.h 中声明
wVersionRequested = MAKEWORD(2, 2);
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != 0) {
//告知用户无法找到合适可用的