我不断通过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;
}
答案 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
。请注意,如果您的平台是小端,则必须进行一些字节重新排列。