【问题标题】:Converting bytes to uint32 in C在 C 中将字节转换为 uint32
【发布时间】:2013-12-24 06:19:51
【问题描述】:

我不断地通过 TCP/IP 从 LabVIEW 向 C 程序发送像素值数组 (uint32)。我正在使用 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;
}

【问题讨论】:

  • 由于您没有显示/描述如何发送数据,因此有关如何接收数据的建议只是猜测。
  • 我将数据作为 uint32 整数的二维数组发送。我首先将字符串长度作为 4 个字节发送(I32 类型转换为字符串。)然后在从 uint32 的二维数组展平后发送字符串。
  • 你最好向代码展示。
  • 它是用 LabVIEW 编写的,我没有足够的声誉来发布图片。

标签: c sockets tcp winsock winsock2


【解决方案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 地址。因为指针算法会知道下一个 int 地址将使用addr+sizeof(int) 获得。

下一期。字节顺序可以不同。见endianness 在这种情况下,我们必须进行转换。要么我们将编写我们的函数。或者我们可以使用 htonl ntohl 。或者看这个手动转换endiannes conversion on stackoverflow

然后来到我的代码:uint32_t *endp=(uint32_t*)(recvbuf+iResult); 将指向我们数组的末尾。所以我们将增加我们的指针直到它等于endp; while(p&lt;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

}

【讨论】:

  • @user2292615 看看有没有帮助
【解决方案2】:

考虑以下几点:

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

输出(我的机器是小端):

0xCEFAEFBE
0x牛肉面
按任意键继续 。 . .

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

【讨论】:

    猜你喜欢
    • 2021-04-30
    • 2019-10-18
    • 2017-02-20
    • 1970-01-01
    • 2016-09-06
    • 2017-05-31
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多