[英]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
以上方法是完全安全的
如果你想要一個更可靠的轉換,你可以使用strncpy
或memcpy
並從給定的索引開始剪切字符串,假設你已經知道傳入的緩沖區,但在我個人看來,我並不真正推薦它,特別是在像這樣的無連接套接字中,需要進行大量計算並調用緩沖區長度,如果您不完全了解自己在做什么,有時就不容易調試。
注意 1 :如果您打算使用第一種方法,請注意不要在等待服務器移動/位置命令或任何數量變量時在緩沖區中包含零。
注意 2 :您可以只發送integer或float ,將其轉換,反之亦然,而無需削減或乘以它。
新的游戲網絡開發人員可能會發現這個答案也很有用,因為除了使用UDP sendto()、recvfrom() 的char*
之外,我們無法發送或接收。
我也遇到了同樣的問題,浪費了 30 分鍾試圖找出我做錯了什么。 但是,最后,我找到了解決方案。 從文檔中我們可以看到htonl()
和ntohl()
函數適用於 32 位無符號整數。 因此,要解決此問題,您必須使用<stdint.h>
unsigned __int32
或uint32_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.