Domanda

I'm continuously sending arrays of pixel values (uint32) from LabVIEW to a C-program through TCP/IP. I'm using the recv function in Ws2_32.lib to receive the bytes, but I have to convert them back to uint32 data type and doesn't really know how to do it in this case. I'll be thankful if anyone shows how to do it.

Thanks in advance

#define DEFAULT_BUFLEN 256

#include<stdio.h>
#include<winsock2.h>

#pragma comment(lib,"ws2_32.lib") //Winsock Library

int main(int argc , char *argv[])
{
    WSADATA wsa;
    SOCKET s , new_socket;
    struct sockaddr_in server , client;
    int c;
    typedef unsigned char bytes[256];
    typedef unsigned int uint32_t;
    int iResult;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;




    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        return 1;
    }

    printf("Initialised.\n");

    //Create a socket
    if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
    {
        printf("Could not create socket : %d" , WSAGetLastError());
    }

    printf("Socket created.\n");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 13000 );

    //Bind
    if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
    {
        printf("Bind failed with error code : %d" , WSAGetLastError());
    }

    puts("Bind done");

    //Listen to incoming connections
    listen(s , 3);

    //Accept and incoming connection
    puts("Waiting for incoming connections...");

    c = sizeof(struct sockaddr_in);
    new_socket = accept(s , (struct sockaddr *)&client, &c);
    if (new_socket == INVALID_SOCKET)
    {
        printf("accept failed with error code : %d" , WSAGetLastError());
    }

    do {    
        iResult = recv(new_socket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("%d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());

        } 
    while( iResult > 0 );

    closesocket(s);
    WSACleanup();

    return 0;
}
È stato utile?

Soluzione

First ensure that your do while block works as expected.

Concerning you question

As we know one dimensional array can be think as pointer to memory block. so

char *ar = recvbuf ;

char x1= *ar; //will get first byte (index 0)
char x2=*(ar+1); //will get second byte (index 1)

Also as array and pointer in our case can be used interchangeable We can access as indexed way too

   char x1=ar[0];// the same as *ar
    char x2=ar[1]; //= *(ar+1);

As you see char will move one byte, but in our case we want to move 4 bytes. so we will make our pointer to point to int.

   int *intarr=(int *) recvbuf ; //recvbuf is address

now we can access and fetch ints using the same syntax

    int x1=*intarr;
    int x2= *(intarr+1); //  *((int*)(ar+4))
//or
    int x1=intarr[0];

And note that if inarr point to for example to address 00004 , (inarr+1) will point to 00004+ 4=00008th address. Cause pointer arithmetic will know that next int address will be obtained using addr+sizeof(int).

Next issue. Bytes order can be different. see endianness On that case we have to make conversion. either we will write our functions. or we can use htonl ntohl . Or see this manual conversion endiannes conversion on stackoverflow

Then coming to my code: uint32_t *endp=(uint32_t*)(recvbuf+iResult); will point to end of our array. so we will increment our pointer until it be equal to endp; while(p<endp) ++p; and simple we will use * dereference operator to get that value. after ++p p will point to next int block,and fetching uint32_t from that address will be equal to *p. And we will increment that until endp

Another option just to use index syntax. so we have to first calculate length of our array. How many ints we got in our array .this will be equal iResult/sizeof(uint32_t) iResult our length in bytes. After that we can access index using *(p+index) or more nice way p[index]

  ...

uint32_t *p=(uint32_t*)recvbuf;
uint32_t *endp=(uint32_t*)(recvbuf+iResult);



//here is accessing
while(p<endp){
    //ntohl(*p) if it was send from begin endian
    uint32_t value=*p;p++;
}

//or
uint32_t *p=(uint32_t*)recvbuf;
size_t len=iResult/sizeof(uint32_t);
//
for(int i=0;i<len;i++){
   uint32_t value= p[i]; //and again if there is endian problem solve it using ntonl htonl

}

Altri suggerimenti

Consider the following:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    uint8_t char byteArray[4] = {0xBE, 0xEF, 0xFA, 0xCE};
    uint32_t int32Word = *(uint32_t *)byteArray;

    printf("%#X\n", int32Word);

#ifdef LITTLE_ENDIAN
    int32Word = ((int32Word & 0xFF000000) >> 24) | 
                ((int32Word & 0x00FF0000) >> 8)  | 
                ((int32Word & 0x0000FF00) << 8)  | 
                ((int32Word & 0x000000FF) << 24);

    printf("%#X\n", int32Word);
#endif

    system("pause");
    return 0;
}

Output (My Machine is Little Endian):

0xCEFAEFBE
0xBEEFFACE
Press any key to continue . . .

If you capture 4 uint8_ts at a time from the stream, you can convert them to an uint32_t. Note that if your platform is little endian, you will have to do some byte rearranging.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top