原始套接字的UDP包效验和怎么算?

classfree 2006-05-01 11:43:01
用原始套接字构造UDP数据包,虚拟IP地址, 但是接收到的数据包的效验和始终和原来的不一样,
代码如下:

typedef struct _iphdr //定义IP首部
{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER, *PIP_HEADER;

typedef struct _udphdr // UDP 数据报
{
unsigned short souceport; //源端口
unsigned short destport; //目的端口
unsigned short length; //数据长度
unsigned short checksum; //带数据!检查和
}UDP_HEADER, *PUDP_HEADER;

WSADATA WSAData;
SOCKET sock;
struct sockaddr_in addr_in;

//效验和
unsigned short checksum(unsigned short *buffer,int size)
{
unsigned long cksum = 0;
while(size > 0) //各位求和
{
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if(size)
cksum += *(unsigned char *)buffer;
cksum = (cksum >> 16) + (cksum & 0xffff); //移位,位与运算
cksum += (cksum >> 16);
return (unsigned short)(~cksum); //再取反
}

//发送数据
void SendData(char *buf, int nLen)
{
IP_HEADER ipHeader;
UDP_HEADER udpHeader;
BOOL blnFlag = TRUE;
//char szSendBuf[256] = {0};
int rect, nTimeOver=100;


//sock = socket(AF_INET, SOCK_DGRAM, 0);
sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if(setsockopt(sock,IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag)) == SOCKET_ERROR)
{
printf("设置自定义IP头失败\n");
return;
}

if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver)) == SOCKET_ERROR)
{
printf("setsockopt SO_SNDTIMEO error!\n");
getch();
return;
}

addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(13125);
addr_in.sin_addr.S_un.S_addr = inet_addr("192.168.1.99");

//填充IP首部
ipHeader.h_lenver = (4<<4 | sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.tos = 0;
ipHeader.total_len = htons(sizeof(ipHeader)+sizeof(udpHeader)+nLen);
ipHeader.ident = 1;
ipHeader.frag_and_flags = 0;
ipHeader.ttl = 128;
ipHeader.proto = IPPROTO_UDP;
ipHeader.checksum = 0;
ipHeader.sourceIP = inet_addr("192.168.1.89");
ipHeader.destIP = inet_addr("192.168.1.99");

//填充UDP首部
udpHeader.souceport = htons(13105);
udpHeader.destport = htons(13125);
udpHeader.length = htons(sizeof(udpHeader)+nLen); //数据长度
udpHeader.checksum = 0;

char *szSendBuf = new char[sizeof(ipHeader)+sizeof(udpHeader)+nLen];
//效验和
memset(szSendBuf, '\0', sizeof(ipHeader)+sizeof(udpHeader)+nLen);
memcpy(szSendBuf, &udpHeader, sizeof(udpHeader));
memcpy(szSendBuf+sizeof(udpHeader), buf, nLen);
udpHeader.checksum = checksum((USHORT *)szSendBuf, sizeof(udpHeader)+nLen);

memset(szSendBuf, '\0', sizeof(ipHeader)+sizeof(udpHeader)+nLen);
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
memcpy(szSendBuf+sizeof(ipHeader), &udpHeader, sizeof(udpHeader));
memcpy(szSendBuf+sizeof(ipHeader)+sizeof(udpHeader), buf, nLen);
memset(szSendBuf+sizeof(ipHeader)+sizeof(udpHeader), 0, 4);
ipHeader.checksum = checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(udpHeader)+nLen);

//合成数据
memcpy(szSendBuf+sizeof(ipHeader)+sizeof(udpHeader), buf, nLen);
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
printf(" UDP.checksum=%x\n IP.checksum=%x\n", udpHeader.checksum, ipHeader.checksum);


//发送数据
rect = sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(udpHeader)+nLen, 0, (struct sockaddr*)&addr_in, sizeof(addr_in));
//rect = sendto(sock, buf, nLen, 0, (struct sockaddr*)&addr_in, sizeof(addr_in));
if (rect == SOCKET_ERROR)
{
printf("send error!:%d\n",WSAGetLastError());
delete[] szSendBuf;
return;
}
else
printf("send ok!\n");
closesocket(sock);
delete[] szSendBuf;
}

int _tmain(int argc, _TCHAR* argv[])
{
if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
{
printf("WSAStartup Error!\n");
return 1;
}

char buf1[] = {0x08, 0x00, 0x00, 0x00, 0xCE, 0x8A, 0x31, 0x75};
char buf2[] = {0x08, 0x00, 0x00, 0x00, 0x23, 0x00, 0x01, 0x00};
SendData(buf1, 8);
SendData(buf2, 8);


WSACleanup();

getch();
return 0;
}


服务器端接收到的正确的UDP包中UDP头的效验和为:
第一个: 0x0D4B 第二个: 0xE94A
我这个程序发送的数据包,服务器端接收到后UDP头的效验和与上面的不一样,所以数据发送过去了,
但是服务器端没有动作....
请个位大虾帮忙看看.. 谢谢!
...全文
221 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
classfree 2006-05-04
  • 打赏
  • 举报
回复
谢谢,问题解决
周江涛 2006-05-02
  • 打赏
  • 举报
回复
memset(szSendBuf+sizeof(ipHeader)+sizeof(udpHeader), 0, 4);

这一句我没看懂。4 是你的那个nLen吗?在checksum之前清成0?
fakoo 2006-05-02
  • 打赏
  • 举报
回复
大哥,你错在这儿:检验和函数中:while(size > 0) 应该是while(size>1),如果是>0话,当数据为单数个字节时,最后那个数据加得有错(多加了一次),呵呵,不小心啊。我的邮箱是fakoo@126.com对网络编程有兴趣。
classfree 2006-05-02
  • 打赏
  • 举报
回复

//memset(szSendBuf+sizeof(ipHeader)+sizeof(udpHeader), 0, 4);
不好意思,这句是注释了的,
其实这句注释与否,结果都一样的, 我抓包来看过了
麻烦再帮我看看
gudulyn 2006-05-01
  • 打赏
  • 举报
回复
记得pppoe的协议里面有这个东西

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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