读书人

关于mfc下udp发送数据包的有关问题

发布时间: 2012-03-24 14:00:46 作者: rapoo

关于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
[解决办法]
给你一个:

C/C++ code
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");
————————————————————
不解释。。。。。。。。

读书人网 >C++

热点推荐