我必须通过网络传输一些值作为命令,我希望尽可能高效和健壮,即我需要意见来使用这些命令, #defines或enums?
命令的范围不应超过20个命令(假设对命令的每个定义的响应都是40个),所以根据我听过的大多数事情,它很适合char限制。
到目前为止,我假设最好的方法是使用枚举。
答案 0 :(得分:4)
在互联网上传输数字值时,您需要记住两件事。
第一个是endianess,即字节(或有时是位)出现的顺序。假设你有32位值0xAABBCCDD。 Intel CPU是little-endian机器,这意味着这些字节将存储为{0xDD,0xCC,0xBB,0xAA}。换句话说,最低有效字节存储在最低地址。在大端机器中,字节将存储为{0xAA,0xBB,0xCC,0xDD},最低有效字节位于最高地址。
在两台机器之间传输多字节整数时,必须确保它们都能正确地解释彼此的数据,即使它们具有不同的字节顺序。值得庆幸的是,有一个称为网络字节顺序的标准,它是big-endian,并且有4个有用的函数用于在主机顺序和网络顺序之间进行转换:
ntohl(网络托管,长期)
ntohs(网络托管,简称)
htonl(主机到网络,长)
htons(主机到网络,简称)
长版本使用32位整数和带有16位整数的短版本。只要您在通过网络传输数据之前始终调用* hton **并在从网络读取时调用* ntoh **,数据将按正确的字节顺序排列。
当然,解决这个问题的最简单方法,特别是因为你只有20个命令,就是使用单个字节,或 char 。
您必须处理的第二个问题是编码。签名整数是如何表示的?使用符号位?两个补充?同样,当网络上的不同平台使用不同的表示时,您会遇到问题。如果你坚持使用无符号类型,那么你应该没有问题。
用于在程序中表示命令的内容完全取决于您。只需确保您很好地定义协议,并在传输和读取数据时遵守该协议。
例如:
enum command_t { one, two, three }
void send_command(command_t c) {
send((unsigned char)c);
}
command_t read_command() {
return (command_t)recv();
}
void send(unsigned char c) { ... }
unsigned char recv() { ... }
答案 1 :(得分:1)
从效率的角度来看,它没有任何区别。 #define或enum只是一种分配数值的方法......真正的诀窍是如何将该值打包到网络上。
那就是说,我同意我在这里看到的其他答案,我认为无论如何你都在担心错误的事情。设计网络协议需要考虑,并使其在许多系统中可移植和可用,通常应该超越效率问题(当然,该规则也有例外)。
答案 2 :(得分:1)
我还建议使用以行分隔的基于文本的协议。除了不必担心enum
- vs。#define
值之外,还有其他一些好处:
为基于文本的协议手动生成一组命令非常容易。考虑在HTTP服务器上测试错误条件:
$ telnet www.yahoo.com 80
Trying 69.147.76.15...
Connected to www-real.wa1.b.yahoo.com.
Escape character is '^]'.
GOAT / HTTP/1.1
我不需要任何想要理解服务器如何响应的东西:
HTTP/1.1 400 Bad Request
Date: Sat, 11 Jul 2009 16:20:59 GMT
Cache-Control: private
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1
这是很好的用于调试。您可以创建一组测试脚本以提供给telnet
/ nc
,它们比任何二进制协议测试脚本都更容易维护。
如果您根据ASCII文本(或UTF-8)定义协议,则无需担心新平台上的低级问题。在处理二进制协议时,字节顺序,结构对齐和字大小都是问题。 ASCII可能需要额外的序列化/反序列化步骤,但是在通常需要的网络协议中。
如果您想与项目中的其他人合作,能够将网络操作描述为普通文本非常棒。如果其他人想要开发自己的客户端,则不要求他们使用您的头文件或任何东西,他们只需遵守类似RFC的标准。这对宠物项目没有用,但考虑到可能变大的任何东西都是好事。
答案 3 :(得分:0)
您想要意见吗?我的观点是你应该使用基于文本的协议,其中每个命令都是一个关键字。是否以及如何将它们转换为程序中的枚举/取决于您,但在网络级别,使用基于文本的命令意味着您的协议更具可扩展性。
许多现实生活中的协议都是基于文本的,我敢说他们的工作非常有效。例如,HTTP,FTP,SMTP等都是基于文本的。