标签:字符 强制 函数返回 style bool 赋值 signed sizeof packet
#include<iostream> #include<cstdio> #include<cstring> #include<winsock2.h> using namespace std; #define TIME_STAMP_REQUEST 13 struct iphdr { unsigned char ip_hdr_len : 4; //包头长度 unsigned char ip_version : 4; //版本 unsigned char ip_tos; unsigned short ip_length; //总长度 unsigned short ip_identify;//标识 unsigned short ip_offset;//片偏移 unsigned char ip_ttl; unsigned char ip_protocol; unsigned short ip_cksum; struct in_addr ip_src; //源地址 struct in_addr ip_dst; //目的地址 }; struct icmphdr { unsigned char icmp_type; //8位类型 unsigned char icmp_code; //8位代码 unsigned short icmp_cksum; //16位的校验和 unsigned short icmp_identify; unsigned short icmp_seq; unsigned int icmp_otime; unsigned int icmp_rtime; //接收时间 unsigned int icmp_ttime; //应答时间 }; unsigned short checksum(int count,unsigned short* addr) { long sum = 0; while(count > 1) { sum +=*addr++; count -= sizeof(unsigned short); } if(count > 0) { sum +=*(unsigned char*)addr; } while(sum >> 16) { sum = (sum & 0xFFFF) + (sum >> 16); } return (unsigned short)(~sum); } bool timestamp_request(char * argv) { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); SOCKET soc = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if(soc == -1) { printf("create raw socket failed!\n"); return false; } struct sockaddr_in addrsrv; addrsrv.sin_family = AF_INET; addrsrv.sin_port = htons(0); addrsrv.sin_addr.s_addr = inet_addr("202.112.10.36"); //预设地址 struct hostent* phostent = gethostbyname(argv); if (phostent) { addrsrv.sin_addr.s_addr = *(u_long *)phostent->h_addr_list[0];; } printf("sending timestamp request to host [%s]\n",inet_ntoa(addrsrv.sin_addr)); icmphdr ihdr = {0}; ihdr.icmp_type = TIME_STAMP_REQUEST; ihdr.icmp_identify = (unsigned short)GetCurrentProcessId(); ihdr.icmp_cksum = checksum(sizeof(icmphdr),(unsigned short *)&ihdr); if(sendto(soc,(char *)&ihdr,sizeof(ihdr),0,(sockaddr *)&addrsrv,sizeof(addrsrv)) == -1) { printf("send icmp packet failed!\n"); return false; } struct sockaddr_in addrcli; int nlength = sizeof(addrcli); char recv[MAXBYTE] = {0}; struct timeval timeout; timeout.tv_sec = 3000; timeout.tv_usec = 0; setsockopt(soc, SOL_SOCKET,SO_RCVTIMEO, (char*)&timeout,sizeof(timeout)); if(recvfrom(soc,recv,MAXBYTE,0,(sockaddr *)&addrcli,&nlength) == -1) { printf("recv ip packet failed!\n"); return false; } iphdr* piphdr = (iphdr *)recv; if(checksum(piphdr->ip_hdr_len << 2,(unsigned short *)piphdr) != 0) { printf("invalid ip packet!\n"); return false; } icmphdr* pichdr = (icmphdr *)(piphdr + 1); if(checksum(sizeof(icmphdr),(unsigned short *)pichdr) != 0) { printf("invalid icmp packet!\n"); return false; } printf("recv time:[%u] transmit time:[%u]\n",ntohl(pichdr->icmp_rtime),ntohl(pichdr->icmp_ttime)); return true; } int main(int argc,char * argv[]) { if(argc < 2) { return 0; } timestamp_request(argv[1]); }
函数及变量的解释:
WSADATA : 存储由WSAStartup函数返回的数据。
int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData);
启动异步套接字,加载运行库
wVersionRequest : 高阶字段表示小版本号,低位字段表示主版本号
lpWSAData: 指向WSADATA的指针。
int socket( int af, int type, int protocol);
根据指定协议族、数据类型、协议来分配一个套接口
af : 地址描述,目前仅支持AF_INET
type :指定socket类型,SOCK_STREAM是面向连接的socket,SOCK_DGRAME是无连接的socket,SOCK_RAW是原始套接字,可以接收到本机网卡上的数据帧。
protocol : 指定协议。IPPROTO_TCP , IPPROTO_UDP,IPPROTO_ICMP等等
sockaddr_in
作为bind、connect、recvfrom、sendto函数中指明地址的信息。
内部成员:
short sin_family 指明协议族
u_short sin_port 端口号,必须是网络字节流
sin_addr 类型为in_addr,真正存储IP的是s_addr,s_addr其实就是一个 u_int 类型的数据,其中存储的IP地址为网络字节流形式。
in_addr
in_addr 这个结构体中只有一个u_int的变量,用来存储网络字节顺序的IP地址
既然只有一个变量,还定义个毛结构体,出了好多麻烦事
htons(u_short x)
ntohs(u_short x)
将网络字节序的u_short x转变为主机字节序
ntohl(u_long x)
将网络字节序的u_long x转变为主机字节序
in_addr_t inet_addr(const char* strptr);
in_addr_t = u_int
如果字符串有效,把字符串转变为网络字节序的 IPV4地址,返回类型为u_int
gethostbyname(char * name)
通过主机名获得主机的信息
hostent *p
gethostbyname的返回类型
char ** h_addr_list : 主机网络地址的指针,网络字节顺序,以字符串的形式描述一个IP地址,如果对sockaddr_in中存储IP地址的变量进行赋值,需要进行强制转换。
char *inet_ntoa(in_addr in)
将一个in_addr 的网络字节流转换为点分十进制的IP地址
注意 sockaddr_in.sin_addr的类型就是 in_addr,可以作为参数直接传进去
int sendto(SOCKET s,char *buf,int blen,int flags,sockaddr *to,int tlen);
flags 用来改变sendto发送的形式
适用于发送无连接的UDP数据包
标签:字符 强制 函数返回 style bool 赋值 signed sizeof packet
原文地址:http://www.cnblogs.com/jifahu/p/6785768.html