在C中通过套接字传输int
的适当方法是什么?
到目前为止我所做的是:
int n = 4;
int tmp = htonl(n);
write(socket, &tmp, sizeof(tmp));
和
int tmp,n;
read(socket, &tmp, sizeof(tmp));
n = ntohl(tmp);
然而,收到的整数有时为0.并非总是如此,但我们说5次中的2次。它永远不会是其他值,总是为什么?
更新:读取的返回值为-1,错误为:
Resource temporarily unavailable
答案 0 :(得分:10)
这应该没有任何问题,试试这个:
在发件人(服务器)端:
int number_to_send = 10000; // Put your value
int converted_number = htonl(number_to_send);
// Write the number to the opened socket
write(client_socket, &converted_number, sizeof(converted_number));
在接收方(客户端)方面:
int received_int = 0;
return_status = read(client_socket, &received_int, sizeof(received_int));
if (return_status > 0) {
fprintf(stdout, "Received int = %d\n", ntohl(received_int));
}
else {
// Handling erros here
}
希望这会有所帮助。
答案 1 :(得分:9)
首先,您的发件人和收件人计算机上的sizeof(int)
可能会有所不同。因此,我建议您使用int32_t
中的stdint.h
。
此外,不能保证read(..,..,sizeof(int))
将准确读取sizeof(int)
个字节 - 它不能读取任何内容,或者它可以读取更少的字节。所以,正确的变体将是更像这样的东西:
int send_int(int num, int fd)
{
int32_t conv = htonl(num);
char *data = (char*)&conv;
int left = sizeof(conv);
int rc;
do {
rc = write(fd, data, left);
if (rc < 0) {
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
// use select() or epoll() to wait for the socket to be writable again
}
else if (errno != EINTR) {
return -1;
}
}
else {
data += rc;
left -= rc;
}
}
while (left > 0);
return 0;
}
int receive_int(int *num, int fd)
{
int32_t ret;
char *data = (char*)&ret;
int left = sizeof(ret);
int rc;
do {
rc = read(fd, data, left);
if (rc <= 0) { /* instead of ret */
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
// use select() or epoll() to wait for the socket to be readable again
}
else if (errno != EINTR) {
return -1;
}
}
else {
data += rc;
left -= rc;
}
}
while (left > 0);
*num = ntohl(ret);
return 0;
}
答案 2 :(得分:0)
由于没有人提及sprintf
您可以使用它将任何变量转换为char*
并发送
if(strcmp(buf,"movUP") == 0)
{
char* msg = calloc(1, 20);
pos.y += 0.0001f;
sprintf(msg,"NEW::POS::Y=%.4f", pos.y);
sendto(master, msg, 20, 0, (struct sockaddr*)&client, addrlen);
}
movUP
NEW::POS::Y=0.0001
movUP
NEW::POS::Y=0.0002
movUP
NEW::POS::Y=0.0003
movUP
NEW::POS::Y=0.0004
对整数使用%d
,对于浮点数使用%f
将转换回为整数,使用atoi(char*)
要转换回到浮点数,请使用atof(char*)
转换前,请务必使用strstr()
从"0"
float myPos; // floating variable that stores Object's Position in the World
...
....
memset(buf, 0, MAXBUFFER); // clears the previous buffer
recvfrom(master, buf, MAXBUFFER, 0, (struct sockaddr*)&server, &addrlen);
char* newY = strstr(buf, "0");// NEW::POS::Y=0.0001 --->> 0.000100
myPos = atof(newY); // new object's position by the server
printf("My New Position is %.4f\n", myPos); // Out: My New Position is 0.0011 -> 0.0012 -> 0.0013 -> 0.0014.
对于整数(不位置),您可以使用相同的技术,只需将其乘以
float f = 0.000002f; // that is supposed to be 2 integer value
int i = (int)(f*1000000); // now, i = 2
以上方法完全安全
如果你想要一个更加可靠的转换,你可以使用strncpy
或memcpy
并从一个给定的索引开始剪切字符串,假设你已经知道了传入的缓冲区,但在我的个人看来,我并不是真的推荐它,特别是在像这样的无连接套接字中,大量的计算和调用缓冲区长度,如果你不完全清楚的话有时不容易调试你正在做什么。
注1 :当您等待缓冲区时,请注意不 零 对于服务器移动 / 位置命令或任何 数量变量,如果您计划使用第一方法。
注2 :您只需发送整数或浮动,转换和副反之亦然,无需削减或乘以。
5月新游戏网络开发人员发现这个答案也很有用,因为除了char*
UDP sendto(),recvfrom()之外,我们无法发送或接收。
答案 3 :(得分:0)
我也遇到了同样的问题,浪费了30分钟试图找出我做错了什么。但是,最后,我找到了解决方案。从documentation中我们可以看到htonl()
和ntohl()
函数可以使用32位无符号整数。因此,要解决此问题,您必须使用unsigned __int32
中的uint32_t
或<stdint.h>
。
所以代码将如下所示:
#include <stdint.h>
uint32_t n = 4;
uint32_t tmp = htonl(n);
write(socket, &tmp, sizeof(tmp));
和:
#include <stdint.h>
uint32_t tmp,n;
read(socket, &tmp, sizeof(tmp));
n = ntohl(tmp);