关于mfc下udp发送数据包的问题!
前提是这样的,我要做一个客户端,用udp的形式向服务器发送请求。可是我怎么调试也觉得udp中的sendto函数,返回值为-1;在此请教高手指点!!!代码如下:
.h
typedef struct ip_address
{
unsigned char byte1;
unsigned char byte2;
unsigned char byte3;
unsigned char byte4;
}Ip_Address;
typedef struct udp_headr
{
unsigned short s_port; //16位源端口
unsigned short d_port; //16位目的端口
unsigned short length;
unsigned short checkSum; //16位校验和
} Udp_Head;
typedef struct ip_headr //定义IP首部
{
unsigned char h_verlen; //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_Head;
typedef struct tsd_headr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_Headr;
.cpp
char szSendBuf[60]={0};
int rect;
Udp_Head udphead;
Ip_Head iphead;
PSD_Headr psdHeader;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return ;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup( );
return ;
}
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(9999);
udphead.s_port = htons(59080);
udphead.d_port = htons(9999);
udphead.length = (sizeof(udphead)/4<<4|0);;
udphead.checkSum= 0x196c;
iphead.h_verlen = (4<<4 | sizeof(iphead)/sizeof(unsigned long));
iphead.tos = 0;
iphead.total_len = 113;
iphead.ident = 1;
iphead.frag_and_flags = 0;
iphead.ttl = 128;
iphead.proto = 0x11;
iphead.checksum = 0;
iphead.sourceIP = inet_addr("192.168.102.75");
iphead.destIP = inet_addr("255.255.255.255");
memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
memcpy(szSendBuf+sizeof(psdHeader), &udphead, sizeof(udphead));
memcpy(szSendBuf, &iphead, sizeof(iphead));
memcpy(szSendBuf+sizeof(iphead), &udphead, sizeof(udphead));
memset(szSendBuf+sizeof(iphead)+sizeof(udphead), 0, 4);
memcpy(szSendBuf, &iphead, sizeof(iphead));
rect = sendto(sockClient, szSendBuf, sizeof(iphead)+sizeof(udphead)+1,
0, (struct sockaddr*)&addrSrv, sizeof(addrSrv));
if (rect == SOCKET_ERROR)
{
printf("send error!:%d\n",WSAGetLastError());
return ;
}
else
printf("send ok!\n");
getchar();
closesocket(sockClient);
WSACleanup();
[解决办法]
弱弱的文一句UDP发包,为什么拼IP啊什么包头啊。
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");
-->这里是你服务器地址么?
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(9999);
-->这里是你服务器监听地址么?
中间那些拼头的部分,全删掉,没用的。
...
rect = sendto(sockClient,
szSendBuf,60,
struct sockaddr*)&addrSrv, sizeof(addrSrv));
SOCK_DGRAM 你既然发得时数据报,内核自然会给你在IP层把UDP 啊 IP 包头给你加上,你不用直接拼,拼了也没用。
[解决办法]
首先:SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);// 有误
发送你自己构造的数据包,要选择 原始套接字
2.iphead.checksum = 0;
校验和还是自己算一算,网上算法实现很多,自己去找找
3.还得自己设置一下套接字属性 setsockopt
[解决办法]
给你一个:
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);}int SendUdpPacket(int Port, char *DestIp){ typedef struct IpHeader { u_char Version_HLen; u_char TOS; short Length; short Ident; short Flags_Offset; u_char TTL; u_char Protocol; short Checksum; unsigned int SourceAddr; unsigned int DestinationAddr; } Ip_Header; typedef struct PsdTcpHeader { unsigned int SourceAddr; unsigned int DestinationAddr; u_char Zero; u_char Protocol; unsigned short UdpLength; } PsdTcp_Header; typedef struct UdpHeader { u_short SrcPort; u_short DstPort; u_short Length; u_short Checksum; } Udp_Header; struct in_addr localaddr; char HostName[255]; struct hostent *Hostent; WSADATA wsaData; SOCKET SendSocket; SOCKADDR_IN addr_in; Ip_Header ipHeader; Udp_Header udpHeader; PsdTcp_Header psdudpHeader; char szSendBuf[100] = { 0 }; BOOL flag; int nTimeOver; int Result; Result = WSAStartup(MAKEWORD(2, 1), &wsaData); if (Result == SOCKET_ERROR) { printf("WSAStartup failed with error %d\n", Result); return 0; } if ((SendSocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("WSASocket failed with error %d\n\n", WSAGetLastError()); return false; } flag = true; if (setsockopt(SendSocket, IPPROTO_IP, IP_HDRINCL, (char*) &flag, sizeof(flag)) == SOCKET_ERROR) { printf("setsockopt failed with error %d\n\n", WSAGetLastError()); return false; } nTimeOver = 1000; if (setsockopt(SendSocket, SOL_SOCKET, SO_SNDTIMEO, (char*) &nTimeOver, sizeof(nTimeOver)) == SOCKET_ERROR) { printf("setsockopt failed with error %d\n\n", WSAGetLastError()); return false; } addr_in.sin_family = AF_INET; addr_in.sin_port = htons(1000); addr_in.sin_addr.S_un.S_addr = inet_addr(DestIpAddr); Result = gethostname(HostName, 255); if (Result == SOCKET_ERROR) { printf("gethostname failed with error %d\n", WSAGetLastError()); return 0; } Hostent = (struct hostent*)malloc(sizeof(struct hostent)); Hostent = gethostbyname(HostName); memcpy(&localaddr, Hostent->h_addr_list[0], Hostent->h_length); ipHeader.Version_HLen = (4 << 4 | sizeof(ipHeader) / sizeof(unsigned long)); ipHeader.TOS = 0; ipHeader.Length = htons(sizeof(ipHeader) + sizeof(udpHeader)); ipHeader.Ident = 1; ipHeader.Flags_Offset = 0; ipHeader.TTL = 128; ipHeader.Protocol = IPPROTO_UDP; ipHeader.Checksum = 0; ipHeader.SourceAddr = localaddr.S_un.S_addr; ipHeader.DestinationAddr = inet_addr(DestIp); udpHeader.DstPort = htons(Port); udpHeader.SrcPort = htons(6666); udpHeader.Length = htons(sizeof(udpHeader)); udpHeader.Checksum = 0; psdudpHeader.SourceAddr = ipHeader.SourceAddr; psdudpHeader.DestinationAddr = ipHeader.DestinationAddr; psdudpHeader.Zero = 0; psdudpHeader.Protocol = IPPROTO_UDP; psdudpHeader.UdpLength = htons(sizeof(UdpHeader)); memcpy(szSendBuf, &psdudpHeader, sizeof(psdudpHeader)); memcpy(szSendBuf + sizeof(psdudpHeader), &udpHeader, sizeof(udpHeader)); udpHeader.Checksum = checksum((USHORT*)szSendBuf, sizeof(psdudpHeader) + sizeof(udpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); memcpy(szSendBuf + sizeof(ipHeader), &udpHeader, sizeof(udpHeader)); ipHeader.Checksum = checksum((USHORT*)szSendBuf, sizeof(ipHeader) + sizeof(udpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); Result = sendto(SendSocket, szSendBuf, sizeof(ipHeader) + sizeof(udpHeader), 0, (struct sockaddr*) &addr_in, sizeof(addr_in)); if (Result == SOCKET_ERROR) { printf("failed with error %d\n", WSAGetLastError()); return 0; } if (closesocket(SendSocket) == SOCKET_ERROR) { printf("closesocket failed with error %d\n", WSAGetLastError()); return 0; } if (WSACleanup() == SOCKET_ERROR) { printf("WSACleanup failed with error %d\n", WSAGetLastError()); return 0; } return 1;}
[解决办法]
addrSrv.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");
————————————————————
不解释。。。。。。。。