簡體   English   中英

通過 C 中的套接字傳輸整數

[英]transfer integer over a socket in C

通過 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 次。 它永遠不是其他值,總是 0。為什么?

更新:讀取的返回值為 -1,錯誤為:

Resource temporarily unavailable

首先, sizeof(int)在您的發送方和接收方機器上可能不同。 所以我建議你使用stdint.h int32_t東西。

此外,不能保證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;
}

這應該沒有任何問題,試試這個:

在發送方(服務器)端:

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
}

希望這會有所幫助。

由於沒有人提到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 :您可以只發送integerfloat將其轉換,反之亦然,而無需削減乘以它。

新的游戲網絡開發人員可能會發現這個答案也很有用,因為除了使用UDP sendto()、recvfrom() 的char*之外,我們無法發送或接收。

我也遇到了同樣的問題,浪費了 30 分鍾試圖找出我做錯了什么。 但是,最后,我找到了解決方案。 文檔中我們可以看到htonl()ntohl()函數適用於 32 位無符號整數。 因此,要解決此問題,您必須使用<stdint.h> unsigned __int32uint32_t

所以代碼看起來像這樣:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM