我的代码中有一个问题,应该在udp上发送浮点数。如果我检查我的端口收据,我只会收到随机符号而不是我想要的号码。
printf("Lets send some cool data \n");
int clientSocket;
struct sockaddr_in serverAddress;
socklen_t addressSize;
unsigned char l_remoteHostAddr_rg4ui8[4] = {192,168,22,160};
unsigned short l_remoteHostPort_ui16 = 5000;
int l_udpSocket_i32;
unsigned int l_sendState_bl;
// open udp connection
l_udpSocket_i32 = g_halMatlab_initConnection_i32( l_remoteHostAddr_rg4ui8, l_remoteHostPort_ui16 );
halImu_orientationValues l_imuMeasurements_st;
g_halImu_initImuSensors_bl();
/*Create UDP socket*/
clientSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
serverAddress.sin_family = PF_INET;
serverAddress.sin_port = htons(REMOTE_PORT);
serverAddress.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
memset(serverAddress.sin_zero, '\0', sizeof(serverAddress.sin_zero));
/*Initialize size variable to be used later on*/
addressSize = sizeof(serverAddress);
printf("Start Sending Messages\n");
int i = kbhit();
while(i != 'q')
{
sleep(1);
g_halImu_triggerImuReading_bl();
g_halImu_triggerBaroReading_bl();
g_halImu_triggerGyroReading_bl();
g_halImu_triggerAccReading_bl();
l_imuMeasurements_st=g_halImu_getImuValues_str();
l_sendState_bl = g_halMatlab_sendImuState_bl(l_udpSocket_i32, l_imuMeasurements_st);
printf("Acc X %f \n", l_imuMeasurements_st.acc.x_f64);
float k = l_imuMeasurements_st.acc.x_f64;
char imu_x[16];
sprintf(imu_x,"%f \n",k);
printf(imu_x,'\n'); //this prints the right number
sendto(clientSocket, imu_x, (int)sizeof(imu_x), 0,
(struct sockaddr *)&serverAddress,addressSize);
printf("And send again....\n");
}
如果我知道使用nc -ul 5000,我会收到包含随机内容的16位字符串。
如果有人知道我的问题可能在哪里,我会很高兴收到你的回复
度过美好的一天!
答案 0 :(得分:2)
imu_x
长度为16个字符,但是当您使用sprintf()
将浮点数放入其中时,它只会有7个字符。空格,换行符和尾随空值再添加3个字符,但字符串中剩余的6个字符将是未初始化的,这可能是您在接收端看到的垃圾。
我建议您发送sizeof(imu_x)
字节,而不是发送strlen(imu_x)
个字节。
答案 1 :(得分:2)
第一个问题是您要发送两次相同的数据。首先通过一个名为clientSocket的套接字,另一个通过另一个名为l_udpSocket_i32的套接字。我正在清理代码,因此只编译了clientSocket。
第二个问题是您尝试打印imu_x的所有16个数据。您应该只打印书面字符。我添加了一个名为written的新变量。运行它,你不会看到任何垃圾。
printf("Lets send some cool data \n");
int clientSocket;
struct sockaddr_in serverAddress;
socklen_t addressSize;
int written;
char imu_x[16];
halImu_orientationValues l_imuMeasurements_st;
g_halImu_initImuSensors_bl();
/*Create UDP socket*/
clientSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
serverAddress.sin_family = PF_INET;
serverAddress.sin_port = htons(REMOTE_PORT);
serverAddress.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
memset(serverAddress.sin_zero, '\0', sizeof(serverAddress.sin_zero));
/*Initialize size variable to be used later on*/
addressSize = sizeof(serverAddress);
printf("Start Sending Messages\n");
int i = kbhit();
while(i != 'q')
{
sleep(1);
g_halImu_triggerImuReading_bl();
g_halImu_triggerBaroReading_bl();
g_halImu_triggerGyroReading_bl();
g_halImu_triggerAccReading_bl();
l_imuMeasurements_st=g_halImu_getImuValues_str();
printf("Acc X %f \n", l_imuMeasurements_st.acc.x_f64);
float k = l_imuMeasurements_st.acc.x_f64;
written = sprintf(imu_x,"%f \n",k);
printf(imu_x,'\n'); //this prints the right number
sendto(clientSocket, imu_x, written, 0,
(struct sockaddr *)&serverAddress,addressSize);
printf("And send again....\n");
}
答案 2 :(得分:1)
除了不完全定义发送的缓冲区(@Barmar)之外,将float
打印到这样一个小缓冲区中很容易过度流动。
float k = l_imuMeasurements_st.acc.x_f64;
char imu_x[16];
sprintf(imu_x,"%f \n",k);
如果k
的值为1.2345,则imu_x[]
将成为"1.234500 \n"
- 至少需要11 char
。如果k
的值类似于-12345,那么结果将为"-12345.000000 \n"
,并且需要16 char
。很容易看出稍微大一点的值会如何溢出缓冲区。一旦发生这种情况,其余代码就是未定义的行为。
相反,建议清除缓冲区并在打印时使用%e
,以便为float
的整个范围提供重要数据。在小数点后指定13和5位的宽度。使用snprintf()
,缓冲区不会过满。通过使用宽度为13(空格为+3,\ n和\ 0),缓冲区将始终打印到前16 char
。
memset(imu_x, 0 , sizeof imu_x);
// sign dig . digs e sign expo space \n \0
// 1 1 1 5 1 1 3 1 1 1
snprintf(imu_x, sizeof imu_x, "%13.5e \n",k);