“VC在局域网中通过http协议获取公网IP地址”以及“多个服务器节点的测速代码”

  1. VC在局域网中通过http协议获取公网IP地址

  2. 最后还是用http协议请求解决了,使用wireshark截取了这个请求的内容,然后通过套接字发送给服务器,于是得到想要的ip地址: 
  3.  
  4. #pragma comment(lib, "ws2_32.lib") 
  5. #include<iostream> 
  6. #include<WinSock2.h> 
  7. using namespace std; 
  8.  
  9. void main() 
  10.     char peer[] = "GET / HTTP/1.1\r\n\ 
  11.                   User-Agent:My_Agenter\r\n\ 
  12.                   Host:ip.dnsexit.com\r\n\r\n"; 
  13.     WSADATA A; 
  14.     WSAStartup(MAKEWORD(2,2),&A); 
  15.     SOCKET a=socket(2,1,0); 
  16.     hostent *p=gethostbyname("ip.dnsexit.com");//获取主机地址 
  17.     sockaddr_in addr; 
  18.     addr.sin_addr=*(in_addr*)p->h_addr_list[0];//使用地址列表的第一个进行连接,实际上也只有这一个 
  19.     //addr.sin_addr.S_un.S_addr=::inet_addr("67.214.175.69 \r\n");//这个是可以的,想说明函数inet_addr(char *ip)可以接受ip字符串末尾有空格和换行符而不受影响 
  20.     addr.sin_family=2; 
  21.     addr.sin_port=htons(80);//http的80端口 
  22.     connect(a,(sockaddr*)&addr,sizeof(sockaddr_in)); 
  23.     send(a,peer,sizeof(peer),0);//发送http的GET请求 
  24.     char text[600]={0}; 
  25.     recv(a,text,sizeof(text),0);//接受服务器返回的值 
  26.     int i=0; 
  27.     while(text[i]!='\n'||text[i+1]!='\r')//去掉前面的信息 
  28.         i++; 
  29.     char ip[20]; 
  30.     strcpy(ip,&text[i+3]);//得到ip地址开始位置,复制到字符串ip中 
  31.     puts(ip); 
  32.     closesocket(a); 
  33.     WSACleanup(); 

原文:http://blog.csdn.net/jokers_i/article/details/6715627

 

[cpp]  view plain copy
  1. 最后还是用http协议请求解决了,使用wireshark截取了这个请求的内容,然后通过套接字发送给服务器,于是得到想要的ip地址:  
  2.   
  3. #pragma comment(lib, "ws2_32.lib")  
  4. #include<iostream>  
  5. #include<WinSock2.h>  
  6. using namespace std;  
  7.   
  8. void main()  
  9. {  
  10.     char peer[] = "GET / HTTP/1.1\r\n\  
  11.                   User-Agent:My_Agenter\r\n\  
  12.                   Host:ip.dnsexit.com\r\n\r\n";  
  13.     WSADATA A;  
  14.     WSAStartup(MAKEWORD(2,2),&A);  
  15.     SOCKET a=socket(2,1,0);  
  16.     hostent *p=gethostbyname("ip.dnsexit.com");//获取主机地址  
  17.     sockaddr_in addr;  
  18.     addr.sin_addr=*(in_addr*)p->h_addr_list[0];//使用地址列表的第一个进行连接,实际上也只有这一个  
  19.     //addr.sin_addr.S_un.S_addr=::inet_addr("67.214.175.69 \r\n");//这个是可以的,想说明函数inet_addr(char *ip)可以接受ip字符串末尾有空格和换行符而不受影响  
  20.     addr.sin_family=2;  
  21.     addr.sin_port=htons(80);//http的80端口  
  22.     connect(a,(sockaddr*)&addr,sizeof(sockaddr_in));  
  23.     send(a,peer,sizeof(peer),0);//发送http的GET请求  
  24.     char text[600]={0};  
  25.     recv(a,text,sizeof(text),0);//接受服务器返回的值  
  26.     int i=0;  
  27.     while(text[i]!='\n'||text[i+1]!='\r')//去掉前面的信息  
  28.         i++;  
  29.     char ip[20];  
  30.     strcpy(ip,&text[i+3]);//得到ip地址开始位置,复制到字符串ip中  
  31.     puts(ip);  
  32.     closesocket(a);  
  33.     WSACleanup();  
  34. }  




多个服务器节点的测速代码


RT,经常会有情况,在客户端需要测试到多个服务器节点的速度情况,原理其实很简单,就是向各个节点发一个简单的请求,然后判断应答回来的时间,差值就是响应时间了。

其中有许多可以优化的地方:

1)并发请求,同时向多个服务器发送请求,这样可以将整个测速的时间缩短到串行测速的几分之一

       A)建立n个非阻塞的socket连接到n个服务器

       B)将这n个socket加入到fdWrite,select判断是否可写       C)某socket可写时,即代表连接成功,此时发送请求,并从写套接字集合中清除掉,并加入读套接字集合       D)某socket可读时,代表应答回来,此时计算响应时间,并从读套接字集合中清除掉,并关掉套接字

2)只根据需求测试需要用到的服务器数量,有足够可用服务器后,不再测试其他服务器。因为我们的网络状况,除非双线接入的网络,否则对于电信和联通的服务器必然会有一两个响应非常慢,这种测试是无意义的

      A)在上述select循环时检测已经测速完成的服务器数,如果数量已经足够则退出循环

      B)初始化时为所有服务器节点的响应时间赋一个极大值,表示测速失败

3)保证测速函数互斥访问,同一时间调用多次是毫无意义的,而且会干扰结果

      A)使用一个静态变量表示是否正在测速过程中,如果在则直接返回(不要使用临界区,多次连续的测速也毫无意义 )

 

实现代码如下 ,将自己需要的请求赋给strRequest即可

 

//测试Web服务器的响应

void TestWebServer()

{

static bool bInPorcess = false;// 不要重复测速

 

if (bInPorcess)

return;

 

bInPorcess = true;

 

//  构造HEAD方法请求头 

CStringA strReqest;

 

LockServerAddrArray();

std::vector<ServInfo> serverArray = m_serverArray;

UnLockServerAddrArray();

 

static int nTestCount = 0;//统计测试累计次数

++nTestCount;

mainLog()->write_log(em_utility::ll_normal, "第%d次测试速度。。。", nTestCount);

 

char buf[1500];

typedef std::map<ULONG, ServInfo> ServMap;

ServMap servMap;

 

for (ServerInfoList::iterator iter = serverArray.begin(); iter != serverArray.end(); ++iter)

{

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

ULONG ul;

 

ul = 1;

ioctlsocket(sock, FIONBIO, &ul); //设置为非阻塞模式

 

SOCKADDR_IN saServer;

 

saServer.sin_family = AF_INET;   

saServer.sin_port = htons(80);    

saServer.sin_addr.s_addr = inet_addr(iter->strIP);

connect(sock, (struct sockaddr *)&saServer, sizeof(saServer));

servMap[sock] = *iter;

iter->nResponeTime = 0xEFFF;

}

mainLog()->write_log_2("begin waiting...");

DWORD dwStartTime = GetTickCount();

fd_set fdSocket;

FD_ZERO(&fdSocket);

for (ServMap::iterator iter = servMap.begin(); iter != servMap.end(); ++iter)

{

FD_SET(iter->first, &fdSocket);

}

timeval tv = {6, 0};

fd_set fdWriteTotal = fdSocket;

fd_set fdReadTotal;

FD_ZERO(&fdReadTotal);

int nTestedCount = 0;

 

while (nTestedCount < 5)// 多余的服务器不再测速,无意义

{

fd_set fdRead = fdReadTotal;

fd_set fdWrite = fdWriteTotal;

 

if (fdReadTotal.fd_count == 0 && fdWriteTotal.fd_count == 0)

break;

 

int nRet = select(0, &fdRead, &fdWrite, NULL, &tv);

ATLTRACE("select : %d -- %d\n", nRet, GetTickCount() - dwStartTime);

if (nRet > 0)

{

for (int nIndex = 0; nIndex < (int)fdSocket.fd_count; ++nIndex)

{

SOCKET sock = fdSocket.fd_array[nIndex];

 

if (FD_ISSET(sock, &fdWrite))// 可写,发送请求

{

send(sock, strReqest, strReqest.GetLength(), 0);

FD_CLR(sock, &fdWriteTotal);// 清除掉

FD_SET(sock, &fdReadTotal);

ATLTRACE("socket: %d, send! \n", sock);

}

if (FD_ISSET(sock, &fdRead))

{

nRet = recv(sock, buf, sizeof(buf), 0);  // 从webserver获取数据

servMap[sock].nResponeTime = (GetTickCount() - dwStartTime);

 

for (std::vector<ServInfo>::iterator iter = serverArray.begin(); iter != serverArray.end(); ++iter)// 效率比较低的实现,暂时方案

{

if (iter->strIP == servMap[sock].strIP)

{

iter->nResponeTime = servMap[sock].nResponeTime;

}

}

ATLTRACE("socket: %d, read! \n", sock);

closesocket(sock);

FD_CLR(sock, &fdReadTotal);// 不再侦听这个套接字

servMap.erase(sock);

++nTestedCount;

}

}

}

else if (nRet <= 0)// select 超时,退出

{

mainLog()->write_log(em_utility::ll_error, "select ret: %d, error: %d", nRet, WSAGetLastError());

break;

}

}

 

for (ServMap::iterator iter = servMap.begin(); iter != servMap.end(); ++iter)

{

closesocket(iter->first);

}

sort(serverArray.begin(), serverArray.end());

for (std::vector<ServInfo>::iterator iter = serverArray.begin(); iter != serverArray.end(); ++iter)

{

mainLog()->write_log(em_utility::ll_normal, "iter->strServ = %s, iter->strIP = %s, iter->nResponseTime = %d", iter->strServ, iter->strIP, iter->nResponeTime);

}

 

LockServerAddrArray();

m_serverArray = serverArray;

UnLockServerAddrArray();

 

bInPorcess = false;

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值