在C中通过套接字传输整数

时间:2012-02-04 11:08:31

标签: c sockets int

在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

4 个答案:

答案 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

以上方法完全安全

如果你想要一个更加可靠的转换,你可以使用strncpymemcpy并从一个给定的索引开始剪切字符串,假设你已经知道了传入的缓冲区,但在我的个人看来,我并不是真的推荐它,特别是在像这样的无连接套接字中,大量的计算和调用缓冲区长度,如果你不完全清楚的话有时不容易调试你正在做什么。

  

注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);