通过套接字以字符串形式发送数据的好方法是啥?

Posted

技术标签:

【中文标题】通过套接字以字符串形式发送数据的好方法是啥?【英文标题】:What is a good way of sending data as strings through sockets?通过套接字以字符串形式发送数据的好方法是什么? 【发布时间】:2009-12-24 09:49:36 【问题描述】:

因为有几种方法可以通过套接字以字符串的形式交换数据,例如:

使用以下功能:

    sprintf()sscanf() snprintf()sscanf() printf()strtof()

或转换为char,然后作为数组传递

如果您能建议哪种方式以及为什么它比其他方式更有效且更好,或者如果还有其他上面没有提到的方式,我将不胜感激。目前我正在使用最简单的方法,我的意思是sprintf()sscanf() 函数。但我在网上读到,例如使用snprintf()函数更安全。

【问题讨论】:

我一直想说:这不应该是社区维基。 :-) 对不起?我不知道wiki的作用是什么。请解释一下何时参考社区维基而不是? —— 一般来说,主观的问题,没有一个正确的答案应该是维基。 请注意,您不会因回答 wiki 问题而获得任何声誉。不过你可以获得徽章。 感谢并抱歉给您带来问题 【参考方案1】:

如果你只是想发送字符串,你可以用这样的方式逃脱;它以简单的形式进行序列化:包含以下数据大小的标头..(伪代码)

Send( socket, const string& str )

  const size_t len = str.length();
  send( socket, &len, sizeof( len ) );
  send( socket, str.data(), len );


Receive( socket, string& str )

  size_t len;
  receive( socket, &len, sizeof( len ) );
  str.resize( len );
  receive( socket, str.data(), len );

编辑:见评论 1,更快的发送方法是

Send( socket, const string& str, rawmemory& packet )

  const size_t len = str.length();
  packet.Reserve( len + sizeof( len ) );
  packet.ResetOffset();
  packet.CopyFrom( &len, sizeof( len ) );
  packet.CopyFrom( str.data(), len );
  send( socket, packet.Data(), packet.Length() );

【讨论】:

做2次发送意味着将发送两个数据包。您最好使用一些分散收集机制和在单个数据包中发送的所有数据。 (我假设你在这里使用 TCP) @deus-ex-machina399:仅当您在套接字上设置了 TCP_NODELAY 标志时。 你说得对;我自己使用了类似的代码,并且确实保留了一个额外的缓冲区来创建单个数据包,因为我在几个项目中使用 TCP_NODELAY,在这些项目中,必须以相当高的速率发送许多相当小的数据包 这个问题与seliarization无关......而是如何以字符串形式(ASCII模式)发送数据。但是为什么你是 2x 发送和接收?如果未收到数据,则不会执行第二次发送,对吗? 如果你只是发送一个字符串,远程端事先并不知道这个字符串有多大,换句话说,接收方要么预先分配足够的空间,要么分块接收。为了解决这个问题,我的示例首先发送数据的大小,然后发送数据本身。现在,从您在这里的回答中,我开始认为您的问题实际上是关于转换为字符串/从字符串转换,与数据的发送方式无关,对吗?在那种情况下,这个问题与套接字无关。也许提供一个你想要达到的帽子的例子。【参考方案2】:

在 C++ 中你也可以使用StringStream

stringstream ss;
 int i = 1;
 float f = "1.0";
 char separtor = ';';

 ss << i << separtor  << f;

然后您可以使用ss.str().c_str() 提取字符串

ss.str().c_str() 将导致上述情况与

"

1;1.0

"

【讨论】:

感谢您的回复,这很有趣。这在不同操作系统之间通信时有效吗? 谢谢!其实我在网上看到使用stringstream是没用的,见flamingspork.com/blog/2009/08/04/…,再次感谢您的帮助 作者的论点主要集中在具体案例上,我在过去的项目中广泛使用了字符串 Stream,发现它们远非无用。但这是一个完全主观的问题:-)【参考方案3】:

看看Serialization—How to Pack Data。

发送文本数据很容易 通过网络,你会发现, 但是如果你想发送会发生什么 一些“二进制”数据,如整数或 浮动?原来你有几个 选项。

    使用 sprintf() 之类的函数将数字转换为文本,然后 发送文本。接收方将解析 使用 a 将文本重新转换为数字 类似 strtol() 的函数。 只需发送原始数据,将指向数据的指针传递给 send()。 将数字编码为可移植的二进制形式。收件人 将解码它。

【讨论】:

感谢您的回复。对于二进制,没有问题,因为我使用的是谷歌的协议缓冲区,因为交换是在不同的操作系统之间进行的。 那么,您是否建议使用 sprintf() 和 strtol() 就足够了? @mk,也许它有点慢,但它不是一个糟糕的选择 IMO。 我很困惑 - 这个问题与通过套接字发送协议缓冲区消息有关吗?如果是这样,您不是使用提供的 IO 类进行编码/解码吗? code.google.com/apis/protocolbuffers/docs/reference/cpp/… @therefromhere,不,它不是以二进制模式发送数据,而是以字符串(ASCII)发送数据......感谢回复 @Nick D,那么最快的方法是什么(我意思是 ASCII 模式)?谢谢!

以上是关于通过套接字以字符串形式发送数据的好方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

当 API 调用需要以纯文本形式发送密码时,将密码存储在数据库中的最佳方法是啥?

在 Python 中通过套接字发送大量数据的正确方法是啥?

从用户代理中识别 iOS 设备的好方法是啥?

我们如何在 UI 线程中创建处理程序以将数据发送到另一个线程

通过c中的套接字发送结构

通过 Socket C++ 发送长字符串