网络C代码中的数据损坏

时间:2010-06-23 09:06:22

标签: c windows c89

我正在使用Windows和ANSI-c,我有一个应用程序从网卡嗅探数据然后解码它并通过UDP发送到其他应用程序。问题是我的应用程序从精细工作开始,但一段时间后它的所有变量int,浮点数和字符串都已损坏我已经多次检查它但无法解决问题。当我直接将数据直接发送到我的IP而不从网络中嗅探数据时,这个应用程序工作得很好。

任何人都可以建议我如何解决这个问题,任何测试工具或其他可以帮助吗?

//method for start sniffing the raw port
void StartSniffing(SOCKET sniffer)
{
    unsigned char *Buffer = ( unsigned char *)malloc(65536);
    int iPacketLength;
    if (Buffer == NULL)
    {
        printf("malloc() failed.\n");
        return;
    }//end if

    iPacketLength = recvfrom(sniffer,(char *)Buffer,65536,0,0,0); 

    if(iPacketLength > 0 && iPacketLength <50)
        ProcessPacket(Buffer, iPacketLength);
    else
        printf( "recvfrom() failed.\n");

    free(Buffer);
}//end method
//*****************************************************************************************
// method for pecket processing filters udp
void ProcessPacket(unsigned char* Buffer, int Size)
{
    char srtPacketSourceIp[16]={'\0'};
    char strPacketDestinationIp[16] ={'\0'} ;
    strcpy_s(srtPacketSourceIp,inet_ntoa(source.sin_addr));
    strcpy_s(strPacketDestinationIp,inet_ntoa(dest.sin_addr));

    int a=strcmp(srtPacketSourceIp, strSourceIp );
    int b=strcmp(strPacketDestinationIp,strDestinationIp);

    iphdr = (IPV4_HDR *)Buffer;


    switch (iphdr->ip_protocol) //Check the Protocol and do accordingly...
    {
        case 1: //ICMP Protocol
            //PrintIcmpPacket(Buffer,Size);
            break;
        case 2: //IGMP Protocol
            break;
        case 6: //TCP Protocol
            //PrintTcpPacket(Buffer,Size);
            break;
        case 17: //UDP Protocol
            ++udp;          
            if(!strcmp(srtPacketSourceIp, strSourceIp )&& !strcmp(strPacketDestinationIp,strDestinationIp))
                PrintUdpPacket(Buffer,Size);
            break;
        default: //Some Other Protocol like ARP etc.
            break;
    }//end switch

}//end method
//*****************************************************************************************
//method to print ip header for displaing data
void PrintIpHeader (unsigned char* Buffer, int Size)
{
    unsigned short iphdrlen;
    iphdr = (IPV4_HDR *)Buffer;
    iphdrlen = iphdr->ip_header_len*4;
    memset(&source, 0, sizeof(source));
    source.sin_addr.s_addr = iphdr->ip_srcaddr;
    memset(&dest, 0, sizeof(dest));
    dest.sin_addr.s_addr = iphdr->ip_destaddr;
    /*printf("\n");
    printf("IP Header\n");
    printf(" |-IP Version : %d\n",(unsigned int)iphdr->ip_version);
    printf(" |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iphdr->ip_header_len);
    printf(" |-Type Of Service : %d\n",(unsigned int)iphdr->ip_tos);
    printf(" |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iphdr->ip_total_length));
    printf(" |-Identification : %d\n",ntohs(iphdr->ip_id));
    printf(" |-Reserved ZERO Field : %d\n",(unsigned int)iphdr->ip_reserved_zero);
    printf(" |-Dont Fragment Field : %d\n",(unsigned int)iphdr->ip_dont_fragment);
    printf(" |-More Fragment Field : %d\n",(unsigned int)iphdr->ip_more_fragment);
    printf(" |-TTL : %d\n",(unsigned int)iphdr->ip_ttl);
    printf(" |-Protocol : %d\n",(unsigned int)iphdr->ip_protocol);
    printf(" |-Checksum : %d\n",ntohs(iphdr->ip_checksum));
    printf(" |-Source IP : %s\n",inet_ntoa(source.sin_addr));
    printf(" |-Destination IP : %s\n",inet_ntoa(dest.sin_addr));*/

}//end method
//*****************************************************************************************
//method to print udp packet for displaying data
void PrintUdpPacket(unsigned char *Buffer,int Size)
{
    unsigned short iphdrlen;
    iphdr = (IPV4_HDR *)Buffer;
    iphdrlen = iphdr->ip_header_len*4;
    udpheader = (UDP_HDR *)(Buffer + iphdrlen);
    /*printf("\n\n***********************UDP Packet*************************\n");
    PrintIpHeader(Buffer,Size);
    printf("\nUDP Header\n");
    printf(" |-Source Port : %d\n",ntohs(udpheader->source_port));
    printf(" |-Destination Port : %d\n",ntohs(udpheader->dest_port));
    printf(" |-UDP Length : %d\n",ntohs(udpheader->udp_length));
    printf(" |-UDP Checksum : %d\n",ntohs(udpheader->udp_checksum));
    printf("\n");
    printf("IP Header\n");
    PrintData(Buffer,iphdrlen);
    printf("UDP Header\n");
    PrintData(Buffer+iphdrlen,sizeof(UDP_HDR));
    printf("Data Payload\n");
    PrintData(Buffer+iphdrlen+sizeof(UDP_HDR),(Size - sizeof(UDP_HDR) - iphdr->ip_header_len*4));*/
    memcpy(strRecievedDump,Buffer+iphdrlen+sizeof(UDP_HDR),(Size - sizeof(UDP_HDR) - iphdr->ip_header_len*4));
    DumpDecoderAndSender();//this just decodes and sends the data
    //printf("\n###########################################################");

}//end method
//*****************************************************************************************
//method to print data
void PrintData (unsigned char* data , int Size)
{
    for(int i=0 ; i < Size ; i++)
    {
        if( i!=0 && i%16==0) //if one line of hex printing is complete...
        {
            printf(" ");

            for(int j=i-16 ; j<i ; j++)
            {
                if(data[j]>=32 && data[j]<=128)
                    printf("%c",(unsigned char)data[j]); //if its a number or alphabet
                else 
                    printf("."); //otherwise print a dot
            }//end for
            printf("\n");

        }//end if

        if(i%16==0)
            printf(" ");

        printf(" %02X",(unsigned int)data[i]);

        if( i==Size-1) //print the last spaces
        {
            for(int j=0;j<15-i%16;j++)
                (" "); //extra spaces

            printf(" ");

            for(int j=i-i%16 ; j<=i ; j++)
            {
                if(data[j]>=32 && data[j]<=128)
                    printf("%c",(unsigned char)data[j]);
                else 
                    printf(".");
            }//end if
            printf("\n");
        }//end if
    }//end for loop
}//end method   

2 个答案:

答案 0 :(得分:1)

另一个建议是在内存检查程序下运行程序,例如:的valgrind。

答案 1 :(得分:1)

只需2或3分

你的StartSniffing函数没有循环,所以我认为每个收到的数据包都会调用它,在这种情况下,为每个调用分配/释放都是浪费。使用堆栈数组或让调用者分配缓冲区一次并将其传递给被调用者。由于锁定,分配可能会很昂贵。

ProcessPacket中,您声明了2个初始化的数组,然后填充strcpy。删除不必要的初始化程序(隐藏memset次调用)。

然后使用Ip地址比较的结果声明2变量ab,到目前为止一直很好,但是在case 17中你不使用它们并重新检查strcmp这不太好。因此,要么重复使用ab vars,要么完全删除它们。

PrintIpHeader和其他地方避免这些printf通话费用。 printf是昂贵的,所以最好只有一个大呼叫而不是10个小呼叫。这是我的意思的一个例子。

printf("IP Header\n"
       " |-IP Version : %u\n"
       " |-IP Header Length : %u DWORDS or %u Bytes\n"    /* 2 %u but only 1 parameter??? */
       " |-Type Of Service : %u\n"
       " |-IP Total Length : %u Bytes(Size of Packet)\n"
       " |-Identification : %u\n"
       " |-Reserved ZERO Field : %u\n"
       " |-Dont Fragment Field : %u\n"
       " |-More Fragment Field : %u\n"
       " |-TTL : %d\n"
       " |-Protocol : %d\n"
       " |-Checksum : %d\n"
       " |-Source IP : %s\n"
       " |-Destination IP : %s\n", (unsigned int)iphdr->ip_version
                                 , (unsigned int)iphdr->ip_header_len, 9999 /* Added 9999 because the original code was buggy */
                                 , (unsigned int)iphdr->ip_tos
                                 , ntohs(iphdr->ip_total_length)
                                 , ntohs(iphdr->ip_id)
                                 , (unsigned int)iphdr->ip_reserved_zero
                                 , (unsigned int)iphdr->ip_dont_fragment
                                 , (unsigned int)iphdr->ip_more_fragment
                                 , (unsigned int)iphdr->ip_ttl 
                                 , (unsigned int)iphdr->ip_protocol
                                 , ntohs(iphdr->ip_checksum)
                                 , inet_ntoa(source.sin_addr)
                                 , inet_ntoa(dest.sin_addr));  

请注意,%uunsigned int而不是%d的格式,而第二个printf中的格式为false。你应该在启用警告的情况下进行编译,gcc会对此发出警告。