#include <Winsock2.h> #include <stdio.h> #define IP_HDRINCL 2 // Header is included with data. typedef struct _IPHEADER { UCHAR VerHeadLen; //版本号和头长度 UCHAR TOS; //服务类型 USHORT Length; //IP包总长度 USHORT ID; //IP包唯一标识 USHORT Flags; //标志 UCHAR TTL; //生存时间 UCHAR Protocol; //协议 USHORT Checksum; //校验和 ULONG SourceIP; //源IP地址 ULONG DestIP; //目标IP }IPHEADER; typedef struct _UDPHEADER { USHORT SourcePort; //源端口 USHORT DestPort; //目的端口 USHORT Length; //包长度 USHORT CheckSum; //校验和 }UDPHEADER; USHORT checksum(USHORT * buff, int size) { ULONG cksum = 0; while (size > 1) { cksum += *(buff++); size -= sizeof(USHORT); } if(size) { cksum += *((UCHAR*)buff); } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (USHORT)(~cksum); } void UdpHeaderChecksum(IPHEADER *IpHeader,UDPHEADER *UdpHeader,char * payload,int payloadlen) { char buf[1024]; char *ptr = buf; int chksumlen = 0; ULONG zero = 0; //包含源IP地址和目的IP地址 memcpy(ptr,&IpHeader->SourceIP,sizeof(IpHeader->SourceIP)); ptr += sizeof(IpHeader->SourceIP); chksumlen += sizeof(IpHeader->SourceIP); memcpy(ptr,&IpHeader->DestIP,sizeof(IpHeader->DestIP)); ptr += sizeof(IpHeader->DestIP); chksumlen += sizeof(IpHeader->DestIP); //8位0域 memcpy(ptr,&zero,1); ptr += 1; chksumlen += 1; //协议 memcpy(ptr,&IpHeader->Protocol,sizeof(IpHeader->Protocol)); ptr += sizeof(IpHeader->Protocol); chksumlen += sizeof(IpHeader->Protocol); //UDP长度 memcpy(ptr,&UdpHeader->Length,sizeof(UdpHeader->Length)); ptr += sizeof(UdpHeader->Length); chksumlen += sizeof(UdpHeader->Length); //UDP端口号 memcpy(ptr,&UdpHeader->SourcePort,sizeof(UdpHeader->SourcePort)); ptr += sizeof(UdpHeader->SourcePort); chksumlen += sizeof(UdpHeader->SourcePort); memcpy(ptr,&UdpHeader->DestPort,sizeof(UdpHeader->DestPort)); ptr += sizeof(UdpHeader->DestPort); chksumlen += sizeof(UdpHeader->DestPort); //UDP长度 memcpy(ptr,&UdpHeader->Length,sizeof(UdpHeader->Length)); ptr += sizeof(UdpHeader->Length); chksumlen += sizeof(UdpHeader->Length); //16位UDP校验和 memcpy(ptr,&zero,sizeof(UdpHeader->CheckSum)); ptr += sizeof(USHORT); chksumlen += sizeof(USHORT); //净荷 memcpy(ptr,payload,payloadlen); ptr += payloadlen; chksumlen += payloadlen; //补齐到下一个16位边界 for(int i = 0; i < payloadlen %2; i++) { *ptr = 0; ptr++; chksumlen++; } //计算校验和,填充到UDP头 UdpHeader->CheckSum = checksum((USHORT*)buf,chksumlen); } int main() { int i = 0; WSADATA wsaData; int wsaret = WSAStartup(0x101,&wsaData); if(wsaret != 0) { printf("WSAStartup失败\n"); } char szDestIP[] = "192.168.12.110"; char szSourceIP[] = "192.168.12.169"; USHORT nDestPort = 1234; USHORT nSourcePort = 8888; char szMsg[] = "123456"; int nMsgLen = strlen(szMsg); //创建原始套接字 SOCKET sRaw = ::socket(AF_INET,SOCK_RAW,IPPROTO_UDP); //有效IP头包含选项 BOOL bIncl = TRUE; i = ::setsockopt(sRaw,IPPROTO_IP,IP_HDRINCL,(char*)&bIncl,sizeof(bIncl)); char buff[1024] = {0}; int TotalLength = sizeof(IPHEADER) + sizeof(UDPHEADER) + nMsgLen; //IP头 IPHEADER * IpHeader = (IPHEADER*)buff; IpHeader->VerHeadLen = (4 << 4 | (sizeof(_IPHEADER)/sizeof(ULONG))); IpHeader->Length = TotalLength; IpHeader->TTL = 128; IpHeader->Protocol = IPPROTO_UDP; IpHeader->SourceIP = ::inet_addr(szSourceIP); IpHeader->DestIP = ::inet_addr(szDestIP); IpHeader->Checksum = checksum((USHORT*)IpHeader,sizeof(IPHEADER)); //UDP头 UDPHEADER * UdpHeader = (UDPHEADER*)(buff + sizeof(IPHEADER)); UdpHeader->SourcePort = htons(nSourcePort); UdpHeader->DestPort = htons(nDestPort); UdpHeader->Length = htons(sizeof(UDPHEADER) + nMsgLen); UdpHeader->CheckSum = 0; UdpHeaderChecksum(IpHeader,UdpHeader,szMsg,nMsgLen); char* pData = buff + sizeof(IPHEADER) + sizeof(UDPHEADER); memcpy(pData,szMsg,nMsgLen); //设置目的地址 SOCKADDR_IN Addr = {0}; Addr.sin_family = AF_INET; Addr.sin_port = htons(nDestPort); memset(Addr.sin_zero,0,8); Addr.sin_addr.S_un.S_addr = ::inet_addr(szDestIP); //发送原始UDP封包 int nRet = 0; for(i = 0; i < 5; i++) { nRet = sendto(sRaw,buff,TotalLength,0,(sockaddr*)&Addr,sizeof(sockaddr)); if(nRet == SOCKET_ERROR) { printf("sendto() faild:%d\n",WSAGetLastError()); break; } else { printf("send %d bytes\n",nRet); } } closesocket(sRaw); return 0; } 刚开始时,服务程序根本接收不到我发的包,用ethereal抓包时发现数据确实是发送出去了,但显示信息表示UDP校验和不正确。 后来发现计算UDP校验和时,我把IP头也计算进去,实际上,UDP的校验和只需要计算从UDP头开始到后面的净荷。 找到问题后觉得十分简单,但如果有些朋友也犯了和我一样的错误的话,希望有所帮助

UDP 校检和和算法的更多相关文章

  1. SQL Server ->> 校检函数CHECKSUM、CHECKSUM_AGG、BINARY_CHECKSUM和HASHBYTES

    今天特地查了一下SQL Server下的校检函数有哪些.原本我只是在工作中用过一个CHECKSUM,今天特地学习了一下才发现原来还有其他的校检函数. 这里找到了别人对于SQL SERVER下这几个校检 ...

  2. Spring MVC全局异常处理与拦截器校检

    在使用Spring MVC进行开发时,总是要对系统异常和用户的异常行为进行处理,以提供给用户友好的提示,也可以提高系统的安全性. 拦截系统响应错误 首先是拦截系统响应错误,这个可以在web.xml中配 ...

  3. TableView 校检表

    这俩天学习了tableView 校检表 主要就是通过一个方法来跟踪当前选中的行.下面将声明一个NSIndexPath 的属性来跟踪最后选中的行.这篇文章希望能给那些初学者带来学习的乐趣.不说了直接上代 ...

  4. TCP粘包, UDP丢包, nagle算法

    一.TCP粘包 1. 什么时候考虑粘包 如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构,类似于http协议,UDP不会出 ...

  5. 四则运算生成与校检 Python实现

    GitHub地址 https://github.com/little-petrol/Arithmetic.git 合作者: 郭旭 和 卢明凯 设计实现过程 代码的组织主要分为两个部分: 算法与结构体的 ...

  6. 表单数据校检方法 onsubmit()的使用?

    在项目中为一个表单(from)编写onsubmit()脚本的时候,经常需要验证表单中数据的合法性 所以常会写道:<form action="/admin/addUser.do" ...

  7. 批处理--md5校检

    @echo off rem 获取文件xx.zip的MD5 for /f "delims=" %%i in ('md5.exe xx.zip') do (set md5_var=%% ...

  8. Java 中使用正则表达式校检IP是否输入正确

    感谢大佬案例:https://www.jb51.net/article/114671.htm 正则表达式学习:(待办)近期总结

  9. UNP学习笔记(第十八章 路由套接字)

    路由套接字上支持3种类型的操作 1). 进程能通过写路由套接字向内核发消息. 2). 进程能通过路由套接字从内核读消息. 3). 进程可以用sysctl函数得到路由表或列出所有已配置的接口. 数据链路 ...

随机推荐

  1. Introduction to Gaussian Processes

    Introduction to Gaussian Processes Gaussian processes (GP) are a cornerstone of modern machine learn ...

  2. 关于v$sql_bind_capture 的问题

    ---先清空shared_pool SQL> alter system flush shared_pool; System altered. SQL> col value_STRING f ...

  3. vi的撤销命令

    'u' : 撤销上一个编辑操作 'ctrl + r' : 恢复,即回退前一个命令 'U' : 行撤销,撤销所有在前一个编辑行上的操作 使用u 和 CTRL+R 命令可以恢复到任何编辑过的状态

  4. C++ const&的一个特性

    最近在搜索类似scope exit的实现时,除了发现已经有人向标准委员会提出意见,还得到一些意外的C++特性,这个特性一直都存在,而且很有趣 http://herbsutter.com/2008/01 ...

  5. Android Loader详解四:回调及完整例子

    onLoadFinished 这个方法是在前面已创建的装载器已经完成其加载过程后被调用.这个方法保证会在应用到装载器上的数据被释放之前被调用.在此方法中,你必须删除所有对旧数据的使用(因为它将很快会被 ...

  6. android studio class org.bouncycastle.asn1.asn1primitive overrides final method equals

    好吧 上手as 又遇到一个问题: class org.bouncycastle.asn1.asn1primitive overrides final method equals... 项目运行的是后报 ...

  7. Ubuntu 使用apt-get时提示错误:无法获得锁 /var/lib/dpkg/lock

    推荐博客:http://blog.sina.com.cn/s/blog_5c1450a8010188ju.html Ubuntu 使用apt-get时提示错误:无法获得锁 /var/lib/dpkg/ ...

  8. Linux下Java环境变量设置

    我用的是oh my zsh,需要修改.zshrc,记一下免得以后忘记在哪儿改的. 如果你用的是自带的terminal那么用文本编辑器打开用户目录下的.bash_profile文件 在.bash_pro ...

  9. [CODEVS1294]全排列

    题目描述 Description 给出一个n, 请输出n的所有全排列 输入描述 Input Description 读入仅一个整数n   (1<=n<=10) 输出描述 Output De ...

  10. Hdu 4311-Meeting point-1 曼哈顿距离,前缀和

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4311 Meeting point-1 Time Limit: 2000/1000 MS (Java/Oth ...