【问题标题】:C++ Sockets - Can i only send characters?C++ 套接字 - 我只能发送字符吗?
【发布时间】:2010-08-10 22:32:36
【问题描述】:

我正在使用带有 win32 窗口的同步套接字,并使用 send() 和 recv() 函数通过 Internet TCP 发送数据;

我想知道,我将如何通过 tcp 套接字发送一些整数甚至我自己的类/结构?因为 send() 函数只允许我发送字符。

我是否只需要发送字符,然后使用 atoi() 将它们转换为整数?或者如果我想发送一个类结构,我会发送许多字符串然后将它们放入变量中.. 一个接一个。

【问题讨论】:

标签: c++ sockets winapi


【解决方案1】:

它不是在文本意义上发送字符 - 它是发送连续的字节数组,它指的是使用 char*。你可以通过这种方式指向任何值类型的字节,所以如果你想发送一个 int,

int A = 5;
const char* pBytesOfA = (const char*)&A;
int lengthOfBytes = sizeof(A);

send(socket, pBytesOfA, lengthOfBytes, flags);

【讨论】:

  • 我认为你应该在传输之前使用htonl()。
【解决方案2】:

这取决于你想做什么。一种简单的可能性是:

假设int 有 32 个有效位,并且负值以二进制补码形式编码。然后你可以发送一个int作为四个chars

bool send_int(int fd, int i)
{
  unsigned char buf[4];
  buf[0] = (i >> 24) & 0xff;
  buf[1] = (i >> 16) & 0xff;
  buf[2] = (i >>  8) & 0xff;
  buf[3] = (i >>  0) & 0xff;
  return ((unsigned) send(fd, buf, sizeof buf, 0) == sizeof buf);
}

在接收端,您必须读取四个字节,然后组合它们的值,以便它们再次形成int

ints 和其他数据类型编码为字节流还有许多其他可能性。以上只是一个简单的例子。

【讨论】:

  • 不要这样做。我的意思是不要与缓冲区大小进行比较。始终跟踪您发送了多少字节。 write(2)send(2) 可以合法返回少于您要求发送的数量。
  • 感谢您的来信。正确的解决方法是编写一个函数sendbytes,它反复尝试发送给定的缓冲区(或其剩余部分),直到所有字节都已发送或发生不可恢复的错误。
【解决方案3】:

不要自己做这个,使用为你做这个的库,比如Boost.AsioBoost.Serialization

Boost Asio 是一个库,它取代了套接字,甚至提供了一个 interface like C++ iostreams 并会为你处理发送/接收像 int 这样的内置类型。

Boost Serialization 使您能够轻松地序列化您的类,以便您可以通过网络发送它们。

如果您不能使用其他库,则必须通过普通套接字手动发送数据 - 确保不要忘记使用 htons, ntohs, htonl and ntohl functions, or your code will break when the two communicating computers use different endianess (byte order).

小sn-p:

// sender:
unsigned long to_send = 123;
unsigned long to_send_n = htonl(to_send); // convert to network byte order
send(send_socket, (const char*)(&to_send_n), sizeof(unsigned long), flags);

// reciever:
char recv_buf[sizeof(unsigned long)];
recv(recv_socket, recv_buf, sizeof(unsigned long)); //recieve number
unsigned long recieved = ntohl(*((unsigned long*)recv_buf), flags); // convert back to host byte order

由于这些函数仅适用于无符号类型,因此您将仅限于无符号类型..

【讨论】:

    【解决方案4】:

    A C(++) char 与字符不同char 只是一个至少(并且通常精确地)8位的整数类型。 char 通常确实表示一个 ASCII 字符(或者现在,一个 UTF-8 代码单元),但它也可以表示任意二进制数据,send()recv() 就是这种情况.

    现在,有一些协议(例如 SMTP)确实假定数据是文本,并且可能会破坏恰好包含 0x0A(换行)或 0x00(C字符串终止符)。在这种情况下,您确实需要使用像 Base64 这样的二进制到文本编码。但如果您直接使用 TCP,这应该不是问题。

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      • 2020-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多