愿意是模仿trace route,利用原始套接字,發送一個ICMP回顯請求,隨著TTL遞增,獲得途經路由。
但是呢,程式一直不能recvfrom到icmp差錯報文,照常是會收到超時型別的差錯報文的,但卻始終收不到。
程式是已管理員身份運行的。
而程式中回顯應答確實可以被正常recvfrom到。
也嘗試用了wireshark在本地抓包,發現是有ICMP差錯報文反饋回來的,并不是遠程路由等的問題。
很頭疼,網上也查不到類似錯誤,希望大家能指點一二。
void ConnectToHost(char* strHost)
{
m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_sockRaw == INVALID_SOCKET)
{
cerr << "WSASocket() failed " << WSAGetLastError() << endl;
ExitProcess(1);
}
//系結
SOCKADDR_IN localaddr;
ZeroMemory(&localaddr, sizeof(SOCKADDR_IN));
localaddr.sin_family = AF_INET;
localaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
bind(m_sockRaw, (sockaddr*)&localaddr, sizeof(SOCKADDR_IN));
//設定套接字接收超時選項
int ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&m_nTimeout, sizeof(m_nTimeout));
if (ret == SOCKET_ERROR)
{
cerr << "setsockopt(SO_RCVTIMEO) failed " << WSAGetLastError() << endl;
return;
}
//設定套接字發送超時選項
m_nTimeout = 10000;
ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&m_nTimeout, sizeof(m_nTimeout));
if (ret == SOCKET_ERROR)
{
cerr << "setsockopt(SO_SNDTIMEO) failed " << WSAGetLastError() << endl;
return;
}
//填充目的地址
ZeroMemory(&m_addrDest, sizeof(m_addrDest));
m_addrDest.sin_family = AF_INET;
if ((m_addrDest.sin_addr.S_un.S_addr = inet_addr(strHost)) == INADDR_NONE)
{
hostent *host = NULL;
host = gethostbyname(strHost);
if (host != NULL)
{
CopyMemory(&(m_addrDest.sin_addr), host->h_addr_list[0], host->h_length);
}
else
{
cerr << "gethostbyname() failed " << WSAGetLastError() << endl;
return;
}
}
//設定不路由選項
bool bopt = true;
if (setsockopt(m_sockRaw, SOL_SOCKET, SO_DONTROUTE, (char*)&bopt, sizeof(bool)) == SOCKET_ERROR)
{
cerr << "setsockopt(SO_DONTROUTE) failed " << WSAGetLastError() << endl;
return;
}
//為發送緩沖區和接識訓沖區申請記憶體,這里確保是足夠的。
m_nDatasize = DEF_PACKET_SIZE;
m_nDatasize += sizeof(IcmpHeader);
m_ICMPData = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);
m_RecvBuf = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);
if (!m_ICMPData || !m_RecvBuf)
{
cerr << "HeapAlloc() failed " << endl;
return;
}
//往發送緩沖區中填充ICMP資料
ZeroMemory(m_ICMPData, MAX_PACKET);
FillICMPData(m_ICMPData, m_nDatasize);
string str;
if (inet_addr(strHost) == INADDR_NONE)
{
str = strHost;
str += " [";
str += inet_ntoa(m_addrDest.sin_addr);
str += "]";
}
else
str = strHost;
cout << "通過最多 " << m_nMaxhops << " 個躍點跟蹤到 " << str.c_str() << " 的路由:" << endl;
//遞增ttl發送ICMP回顯請求
for (m_nTTL = 1; m_nTTL <= m_nMaxhops && !m_bDone; ++m_nTTL)
{
int ret;
SetTTL(m_sockRaw, m_nTTL);
((IcmpHeader*)m_ICMPData)->checksum = 0;
((IcmpHeader*)m_ICMPData)->seq = m_Seqno++;
m_dwCurrentTick = GetTickCount();
((IcmpHeader*)m_ICMPData)->timestamp = m_dwCurrentTick;
((IcmpHeader*)m_ICMPData)->checksum = checksum((unsigned short*)m_ICMPData, m_nDatasize);
ret = sendto(m_sockRaw, m_ICMPData, m_nDatasize, 0, (SOCKADDR*)&m_addrDest, sizeof(SOCKADDR_IN));
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
cout << "發送超時" << endl;
continue;
}
else
{
cerr << "sendto() failed " << WSAGetLastError()<< endl;
return;
}
}
int fromlen = sizeof(SOCKADDR_IN);
ret = recvfrom(m_sockRaw, m_RecvBuf, MAX_PACKET, 0, (SOCKADDR*)&m_addrFrom, &fromlen);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)
{
cout << "接收超時" << endl;
continue;
}
else
{
cerr << "recvfrom() failed " << WSAGetLastError() << endl;
return;
}
}
//決議接收到的ICMP差錯報文或者回顯應答報文
m_bDone = DecodeRecv(m_RecvBuf, ret, &m_addrFrom, m_nTTL);
Sleep(1000);
}
}

uj5u.com熱心網友回復:
那就是你接收問題或者決議問題uj5u.com熱心網友回復:
是接收的問題。
我后面又嘗試了用WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED)創建一個原始套接字,
然后修改io控制WSAIoctl(RCVALL)選項。
發現除開ICMP差錯報文,其它的資料包都是可以被recvfrom到的。
所以很困惑。
去codeproject上找了一個原始碼,編譯之后也是相同結果。
你說會不會是系統限制?但是系統的tracert可以正常運行啊
uj5u.com熱心網友回復:
想知道大家平時都是用recvfrom就可以直接接受到ICMP差錯報文嗎?uj5u.com熱心網友回復:
注意權限檢查每個函式呼叫的回傳值
uj5u.com熱心網友回復:
我和你遇到了一樣的問題,抓包可以看到收到差錯報文,但是socket用recvfrom方法得不到差錯報文的資料包,不過我是用python來實作。uj5u.com熱心網友回復:
我的問題解決了,原因是windows自帶的防火墻攔截了,所以python沒有收到差錯報文,正常的reply報文是沒有攔截的,關閉windows防火墻或者放通策略就行了。uj5u.com熱心網友回復:
很多所謂的安全措施不都是搬起石頭砸自己的腳嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/119459.html
標籤:網絡編程
上一篇:vc sdk 表格控制元件 求助
