0

I've written a UDP send/receive function to send a struct and listen for another struct back. The bytes have to be sent in a particular order, but this is working OK as I'm using #pragma pack(1). The only problem that I'm having now is that if any Null values (0x00) appear in the struct, the rest of the data after the Null disappears.

I guess there's something fairly simple that I'm doing wrong, but here is my code:

typedef u_int8_t NN;
typedef u_int8_t X;
typedef int32_t S;
typedef u_int32_t U;
typedef char C;

typedef struct{
    X test;
    NN test2[2];
    C test3[4];
    S test4;
} Test;

int main(int argc, char** argv)
{
    Test t;
    memset( &t, 0, sizeof(t));
    t.test = 0xde;
    t.test2[0]=0xad; t.test2[1]=0x00;
    t.test3[0]=0xbe; t.test3[1]=0xef; t.test3[2]=0xde; t.test3[3]=0xca;
    t.test4=0xde; 

    LogOnResponse response;

    udp_send_receive(&t, &response);

    return 0;
}

And here is my send/receive function:

int send_and_receive(void* message, void* reply, int do_send, int expect_reply)
{
    struct sockaddr_in serv_addr;
    int sockfd, i, slen=sizeof(serv_addr);
    int buflen = BUFLEN;
    void* buf = NULL;
    struct timeval tv;
    int n_timeouts=1;
    int recv_retval;

//  printf("Message Size: %d\n", strlen(message));

    if ( (strlen(message)) >= BUFLEN)
        err("Message too big");

    buf = malloc(buflen);

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
        err("socket");

    tv.tv_sec = timeout_seconds;
    tv.tv_usec = timeout_microseconds;
    if( setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0 ){
        err("Setting Timout"); 
    }

    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    if (inet_aton(IP_ADDRESS, &serv_addr.sin_addr)==0)
        err("inet_aton() failed\n");

    //---Timeout Send/Receive loop

    do{
    if(do_send == TRUE){
        strcpy(buf, message);
        if (sendto(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, slen)==-1)
            err("sendto()");
    }

    if (expect_reply == TRUE){
        if( (recv_retval = recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, &slen)) == -1){
            itercount++;    
        }
    }

    }while ((itercount < itermax) && (recv_retval == -1));

    if ( itercount != itermax ){
        memcpy(reply, buf, BUFLEN);
    }
    else{
        reply=NULL;
    }

    close(sockfd);
    free(buf);
    return 0;
}

void udp_send_receive(void* message, void* reply)
{
    send_and_receive(message, reply, TRUE, TRUE);
}

Running the above code and capturing the packets with WireShark shows:

Data: DEAD000000000000000000....

I'd like it to show:

Data: DEAD00BEEFDECADE

I'd really appreciate some pointers on this.

4

3 回答 3

6

您不能对二进制数据使用字符串函数(如strlenor strcpy)。这是因为字符串以零值(字符'\0')终止。

例如,您用于strcpy复制数据,但它会在看到字符串终止符时立即停止,这意味着它不会复制所有数据。

于 2013-09-20T10:34:27.580 回答
2

而不是使用strcpy使用

void * memcpy ( void * destination, const void * source, size_t num );

于 2013-09-20T10:36:00.427 回答
0

在里面做strcpy(buf, message);send_and_receive()不正确的。我会更新代码以传递消息的大小并使用它来复制内存

udp_send_receive(&t, sizeof(t), &response);



void udp_send_receive(void* message, int len, void* reply){

    send_and_receive(message, len reply, TRUE, TRUE);
}

int send_and_receive(void* message, int len, void* reply, int do_send, int expect_reply){

   ...
   int buflen = len;

   ....
   memcpy(buf, message, len); //instead of strcpt(buf, message)

   ...
}
于 2013-09-20T10:42:17.417 回答