c语言 读ttl socket,新人求助,我在写socket编程时遇到的一个奇怪的问题

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

我在用socket 的API写一个traceroute的程序,发送的是ICMP数据包,完成后发现程序跑两三遍没问题,但是之后的话,程序便不能运行了,我查看了一下,ICMP的type类型返回了9,应该返回0的,求教为什么?总是成功两三遍后就没法运行,重开也没有用,只能重启电脑才行。小弟多谢各位了,顺便吐槽下头衔的名字。程序如下

#include "TraceRoute1.h"

void ConnectToHost(char* strHost)

{

m_nTTL = 1;

m_nMaxhops = MAX_HOPS;

m_sockRaw = INVALID_SOCKET;

m_RcvBuffer = NULL;

m_IcmpData = NULL;

m_nTimeout = 1000;

m_bDone = FALSE;

WSADATA wsaData; //存储被WSAStartup函数调用后返回的Windows Sockets数据

if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)

{

printf("初始化出错\n"); //如果结果不为0,初始化WinSock出错

}

m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, //返回新套接口的描述字,失败就返回INVALID_SOCKET

NULL, 0,WSA_FLAG_OVERLAPPED);

//m_sockRaw = 4294967291;

if (m_sockRaw == INVALID_SOCKET)

{

printf("创建套接口出错\n");

ExitProcess(-1);

}

int ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_RCVTIMEO, //设置套接口的属性

(char *)&m_nTimeout, sizeof(m_nTimeout));

if (ret == SOCKET_ERROR) //若无错误发生,setsockopt()返回0。否则的话,返回SOCKET_ERROR错误

{

printf("设置套接口属性出错(接收)\n"); //获得上次失败操作的错误状态.

return ;

}

ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_SNDTIMEO,

(char *)&m_nTimeout, sizeof(m_nTimeout));

if (ret == SOCKET_ERROR)

{

printf("设置套接口属性出错(发送)\n");

return ;

}

//解析地址

m_addrDest.sin_family = AF_INET; //给变量赋值

if ((m_addrDest.sin_addr.s_addr = inet_addr(strHost)) == INADDR_NONE) // 将函数inet_addr(strHost)取得的结果付给变量

//将一个点分十进制的IP转换成一个长整数型数(

// 然后判断两个变量是否相等

{

HOSTENT* hp;

hp = gethostbyname(strHost); //返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针

if (hp)

memcpy(&(m_addrDest.sin_addr), hp->h_addr, hp->h_length); //取指针地址所指的变量,放入函数 memcpy中计算得到结果

else

{

printf("地址解析错误\n");

return ;

}

}

//设置路由选项

int bOpt = TRUE;

if (setsockopt(m_sockRaw, SOL_SOCKET, SO_DONTROUTE, (char *)&bOpt,

sizeof(BOOL)) == SOCKET_ERROR)

{

printf("设置套接口选项失败\n");

return ;

}

m_nDatasize = DEF_PACKET_SIZE;

m_nDatasize += sizeof(IcmpHeader);

//

//为icmp 数据包分配发送和接收缓冲区

m_IcmpData = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);

m_RcvBuffer = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);

//为icmp 数据包分配发送和接收缓冲区

if ((!m_IcmpData) || (!m_RcvBuffer))

{

printf("icmp缓冲区分配失败\n");

return ;

}

//创建icmp数据包

memset(m_IcmpData, 0, MAX_PACKET);

printf("\n追踪目的主机 %s: \n\n", strHost);

fill_icmp_data(m_IcmpData, m_nDatasize);

for(m_nTTL = 1; ((m_nTTL < m_nMaxhops) && (!m_bDone)); m_nTTL++)

{

int bwrote;

set_ttl(m_sockRaw, m_nTTL);

((IcmpHeader*)m_IcmpData)->i_cksum = 0;

((IcmpHeader*)m_IcmpData)->timestamp = GetTickCount(); //返回时间

((IcmpHeader*)m_IcmpData)->i_seq = m_nSeqno++;

((IcmpHeader*)m_IcmpData)->i_cksum = checksum((USHORT*)m_IcmpData,

m_nDatasize);

//发送icmp包到目的端

bwrote = sendto(m_sockRaw, m_IcmpData, m_nDatasize, 0,

(SOCKADDR *)&m_addrDest, sizeof(m_addrDest));

if (bwrote == SOCKET_ERROR)

{

if (WSAGetLastError() == WSAETIMEDOUT)

{

printf("%2d 发送超时.\n", m_nTTL);

continue;

}

printf("发送数据出错\n");

return ;

}

//从目的端读取数据报

int fromlen;

fromlen = sizeof(SOCKADDR);

ret = recvfrom(m_sockRaw, m_RcvBuffer, MAX_PACKET, 0,

(struct sockaddr*)&m_addrFrom, &fromlen);

if (ret == SOCKET_ERROR)

{

if (WSAGetLastError() == WSAETIMEDOUT)

{

printf("接受超时\n");

continue;

}

printf("接受数据出错\n");

return ;

}

m_bDone = decode_resp(m_RcvBuffer, ret, &m_addrFrom, m_nTTL);

Sleep(1000);

}

}

void fill_icmp_data(char * icmp_data, int datasize)

{

IcmpHeader *icmp_hdr;

char *datapart;

icmp_hdr = (IcmpHeader*)icmp_data;

icmp_hdr->i_type = ICMP_ECHO;

icmp_hdr->i_code = 0;

icmp_hdr->i_id = (USHORT)GetCurrentProcessId();

icmp_hdr->i_cksum = 0;

icmp_hdr->i_seq = 0;

datapart = icmp_data + sizeof(IcmpHeader);

memset(datapart,'0', datasize - sizeof(IcmpHeader));

}

int set_ttl(SOCKET s, int nTimeToLive)

{

int nRet;

nRet = setsockopt(s, IPPROTO_IP, IP_TTL, (LPSTR)&nTimeToLive,

sizeof(int));

if (nRet == SOCKET_ERROR)

{

printf("设置套接字选项出错\n");

return 0;

}

return 1;

}

USHORT checksum(USHORT *buffer, int size)

{

unsigned long cksum=0;

while(size > 1)

{

cksum += *buffer++;

size -= sizeof(USHORT);

}

if(size )

cksum += *(UCHAR*)buffer;

cksum = (cksum >> 16) + (cksum & 0xffff);

cksum += (cksum >> 16);

return (USHORT)(~cksum);

}

//释放

void Cleanup()

{

HeapFree(GetProcessHeap(), 0, m_RcvBuffer);

HeapFree(GetProcessHeap(), 0, m_IcmpData);

if (m_sockRaw != NULL)

closesocket(m_sockRaw);

WSACleanup();

}

int decode_resp(char *buf, int bytes, SOCKADDR_IN *from, int ttl)

{

IpHeader *iphdr = NULL;

IcmpHeader *icmphdr = NULL;

unsigned short iphdrlen;

struct hostent *lpHostent = NULL;

struct in_addr inaddr = from->sin_addr;

iphdr = (IpHeader *)buf;

// 32位word转化成byte要*4

iphdrlen = iphdr->h_len * 4;

icmphdr = (IcmpHeader*)(buf + iphdrlen);

//ICMP首部的地址等于IP首部长度+buf

switch (icmphdr->i_type)

{

case ICMP_ECHOREPLY: // 目的地址返回的icmp

lpHostent = gethostbyaddr((const char *)&from->sin_addr,

AF_INET, sizeof(struct in_addr));

if (lpHostent != NULL)

printf("%2d %s (%s)\n", ttl, lpHostent->h_name,

inet_ntoa(inaddr)); //将一个IP转换成一个互联网标准点分格式的字符串。

return 1;

break;

case ICMP_TIMEOUT: // 沿着这条链路返回的路由

printf("%2d %s\n", ttl, inet_ntoa(inaddr));

return 0;

break;

default:

printf("错误!\n");

return 1;

break;

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值