如何通过winsock控制路由器自动重启

水经注GIS
企业官方账号
2008-11-15 12:21:31
请教各位,如何通过winsock控制路由器自动重启?
...全文
2622 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
q413797247 2012-01-06
  • 打赏
  • 举报
回复
....看下,学习下.
M-先生 2011-10-08
  • 打赏
  • 举报
回复
学习了。。哎,要学的真还好多。。
unjing 2010-07-03
  • 打赏
  • 举报
回复
还是不知道啊
饶鹏 2008-11-18
  • 打赏
  • 举报
回复
> recv时一直死在那里

为什么出不去,应该知道吧?代码注释写得很详细,跟踪几次应该很容易找到原因啊。
饶鹏 2008-11-18
  • 打赏
  • 举报
回复
对了,是不是你没在每一行后面加"\r\n"?
饶鹏 2008-11-18
  • 打赏
  • 举报
回复
你是说recv()无法返回?那就是没有收到路由器返回的数据包,所以函数一直等着。
要是这样原因可就多了,有程序内的、有其他软件的、有硬件的,不实际上机测试是说不清的。
建议还是先认真看看winsock的工作方式吧。
水经注GIS 2008-11-17
  • 打赏
  • 举报
回复
我通过wireshark得到的字符串如下,但用TCP_Req函数发送命令后,在recv时一直死在那里,试了多次也不行,不知是哪里出了问题,请指教。
GET /userRpm/SysRebootRpm.htm?Reboot=%D6%D8%C6%F4%C2%B7%D3%C9%C6%F7 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://192.168.1.1/userRpm/SysRebootRpm.htm
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 2.0.50727; .NET CLR 1.1.4322)
Host: 192.168.1.1
Connection: Keep-Alive
Authorization: Basic YWRtaW46YWRtaW4=
饶鹏 2008-11-17
  • 打赏
  • 举报
回复
引用
1.在您给出的“发送重启路由器请求时的HTTP数据的开始部分”代码中只有“GET /userRpm/SysRebootRpm.htm?Reboot=%D6%D8%C6%F4%C2%B7%D3%C9%C6%F7 HTTP/1.1”是通过wireshare能够看到的,其它的代码依据的是什么呢?


一个TCP包可能分几次发送,你找到的只是第一个部分。wireshare有把TCP包完整显示的功能,手头没有软件,只有你自己去试了。

引用
2.我的路由器的用户名和密码都是“admin”,找了一个Base64函数加密后的结果为“XVQsZSz8”不知道是否正确。


其实可以不用管Base64加密,你直接把抓到的包完整的复制到代码里去,直接发送就行了。我是密码经常要变更所以研究了Base64加密方式。

引用
3.我把加密后的字符串加在HTTP请求数据的结尾部分,然后用您在我发的贴子的回复函数去调用,结果没有任务反应,不知道问题出在哪里?代码如下: TCP_Req("192.168.1.1", 80, req_begin_reboot, sizeof(req_begin_reboot), data_len);


查看返回值就知道哪阶段出错了。正常返回后,还要检查返回包头部是不是"HTTP/1.1 200 OK"。
不是的话可能发送的数据不合路由器要求,它拒绝执行。那时返回的包头部应该是"HTTP/1.1 401 N/A"。
lextm 2008-11-16
  • 打赏
  • 举报
回复
原来是HTTP POST的方式重启。通过HttpWebRequest类型自己构造一个类似的HTTP请求,然后看GetResponse是不是能够收到200的回应吧。
yuhaozx 2008-11-16
  • 打赏
  • 举报
回复
学习
饶鹏 2008-11-16
  • 打赏
  • 举报
回复
下面是用到winsock的代码,我也是从网上找的,自己做了一些修改:
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

#define WINSOCK_VERSION MAKEWORD(2,2) // winsock版本

//-----------------------------------------------------------------------------
// Name: TCP_Req()
// Desc: 向指定端口的指定地址发送TCP数据包
// 返回时,输入数据的缓冲区存放接收的数据,输入数据的长度的变量存放接收的数据的长度
// 因为传输的不一定是文本,所以数据结尾没有空字符
//-----------------------------------------------------------------------------
int TCP_Req(char const * const host_name, WORD const host_port,
char * const buffer, int const buffer_size, int &data_len)
{
assert(host_name && *host_name);
assert(buffer && *buffer);
// 缓冲区大小不小于其中的数据长度
assert(buffer_size > 0 && data_len > 0 && buffer_size >= data_len);

// 初始化Winsock
WSADATA wsadata;
if(WSAStartup(WINSOCK_VERSION, &wsadata))
return -1; // 初始化Winsock出错


// 得到主机信息
LPHOSTENT lphostent = gethostbyname(host_name);
if(lphostent == NULL)
{
WSACleanup();
return -2; // 无法得到主机信息
}

// 填写连接地址信息
SOCKADDR_IN saServer;
saServer.sin_family = AF_INET;
saServer.sin_port = htons(host_port);
saServer.sin_addr = *((LPIN_ADDR)*lphostent->h_addr_list);

// 创建Socket,向主机发出连接请求
SOCKET hsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int nRet = connect(hsocket, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
closesocket(hsocket);
WSACleanup();
return -3; // 无法连接到主机
}

// 发送数据包
nRet = send(hsocket, buffer, data_len, 0);
if (nRet == SOCKET_ERROR)
{
closesocket(hsocket);
WSACleanup();
return -4; // 发送数据包出错
}

// 接收数据,直到无数据传入
char *p_buffer = buffer;
int len = buffer_size;
data_len = 0;
nRet = 1;
while(nRet > 0)
{
nRet = recv(hsocket, p_buffer, len, 0);
// 收到数据后,把缓冲空间指针移到收到的数据后,并减少剩余空间大小,为下一次接收做准备
if (nRet > 0)
{
p_buffer += nRet;
len -= nRet;

// 如果某次接收后缓冲空间刚好用光(不会出现空间不够还正常返回的情况(len<0)),则跳出
// 如果这里不处理,recv()收到为0的长度后可能会返回错误(for byte stream sockets only)
if (len == 0)
{
data_len = buffer_size;
break;
}
}
// 数据接收完毕
else if (nRet == 0)
{
data_len = (int)(p_buffer - buffer);
break;
}
// 接收数据时发生错误
else
{
nRet = WSAGetLastError();
// 如果数据过长,缓冲空间放不下,则能放多少就放多少,不返回错误
if (nRet == WSAEMSGSIZE)
{
data_len = buffer_size;
break;
}
// 如果是其他错误,则返回出错
else
{
closesocket(hsocket);
WSACleanup();
return -5; // recv()其他错误
}
}
} // end while

closesocket(hsocket);
WSACleanup();
return 0;
} // end TCP_Req


像这样调用上面函数:
TCP_Req("192.168.1.1", 80, req, sizeof(req), data_len);
饶鹏 2008-11-15
  • 打赏
  • 举报
回复
这是我的机器重启路由器时发送到关键包:

// 发送重启路由器请求时的HTTP数据的开始部分
const char req_begin_reboot[] =
"GET /userRpm/SysRebootRpm.htm?Reboot=%D6%D8%C6%F4%C2%B7%D3%C9%C6%F7 HTTP/1.1\r\n"
"Host: 192.168.1.1\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11\r\n"
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
"Accept-Language: zh-cn,zh;q=0.5\r\n"
"Accept-Encoding: gzip,deflate\r\n"
"Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7\r\n"
"Keep-Alive: 300\r\n"
"Connection: keep-alive\r\n"
"Referer: http://192.168.1.1/userRpm/SysRebootRpm.htm\r\n"
"Authorization: Basic ";

最后还要加上用Base64编码后的用户名和密码。
发送出去后,若路由器接收到,会返回一个http包,包头是"HTTP/1.1 200 OK"。
饶鹏 2008-11-15
  • 打赏
  • 举报
回复
首先说明我在网络方面是个新手,所以方法很土,也没有重用性。
先下一个封包截取器,比如wireshark。然后研究究竟发的哪几个http包起了关键作用。用VC++的winsock库写程序依次发送那几个包就行了(每发一个包后只做最基本的返回包确认)。另外要对网络数据的加密有基本了解,比如Base64加密方式。
lextm 2008-11-15
  • 打赏
  • 举报
回复
有些路由器可以通过SNMP协议接口重新启动。不过要看你用的路由器的具体情况了,很难一概而论。
hornbills 2008-11-15
  • 打赏
  • 举报
回复
路由器其实就是一台计算机,有操作系统,有命令和接口

如果要对路有器操作,重要的不是如何编程,而是熟悉此路由器,同时拥有权限!

7,540

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 VC.NET
社区管理员
  • VC.NET社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧