在C中将字节转换为uint32

时间:2013-12-24 06:19:52

标签: c sockets tcp winsock winsock2

我不断通过TCP / IP将LabVIEW的像素值数组(uint32)发送到C程序。我正在使用Ws2_32.lib中的recv函数来接收字节,但我必须将它们转换回uint32数据类型,并且在这种情况下并不真正知道如何操作。如果有人展示如何做,我会感恩的。

提前致谢

#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;
}

2 个答案:

答案 0 :(得分:1)

首先确保您的do while块按预期工作。

关于你的问题

我们知道一维数组可以被认为是指向内存块的指针。 所以

char *ar = recvbuf ;

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

同样,在我们的例子中,数组和指针可以互换使用 我们也可以作为索引方式访问

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

如您所见,char将移动一个字节,但在我们的例子中,我们想移动4个字节。所以我们会 使我们的指针指向int。

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

现在我们可以使用相同的语法

访问和获取整数
    int x1=*intarr;
    int x2= *(intarr+1); //  *((int*)(ar+4))
//or
    int x1=intarr[0];

请注意,如果inarr指向例如地址00004(inarr+1)将指向 00004+ 4=00008th地址。原因指针算术将知道将使用addr+sizeof(int)获得下一个int地址。

下一期。字节顺序可以不同。见endianness 在这种情况下,我们必须进行转换。要么我们要写我们的功能。或者我们可以使用 htonl ntohl。或者参见本手册转换endiannes conversion on stackoverflow

然后来到我的代码:uint32_t *endp=(uint32_t*)(recvbuf+iResult);将指向我们的数组的结尾。所以我们将增加指针直到它等于endp; while(p<endp) ++p;我们将使用*取消引用运算符来获取该值。在++p p将指向下一个int块之后,从该地址提取uint32_t将等于*p。我们会将其增加到endp

另一种选择就是使用索引语法。所以我们必须先计算数组的长度。我们在数组中得到了多少个。这将等于iResult/sizeof(uint32_t) iResult our length in bytes。之后,我们可以使用*(p+index)或更好的方式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

}

答案 1 :(得分:1)

请考虑以下事项:

#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;
}

输出(我的机器是Little Endian):

  

0xCEFAEFBE
  0xBEEFFACE
  按任意键继续 。 。

如果您从流中一次捕获4 uint8_t个,则可以将它们转换为uint32_t。请注意,如果您的平台是小端,则必须进行一些字节重新排列。