我应该通过网络使用#defines或enums来执行命令吗?

时间:2009-07-11 15:21:55

标签: c enums network-programming performance network-protocols

我必须通过网络传输一些值作为命令,我希望尽可能高效和健壮,即我需要意见来使用这些命令, #defines或enums?

命令的范围不应超过20个命令(假设对命令的每个定义的响应都是40个),所以根据我听过的大多数事情,它很适合char限制。

到目前为止,我假设最好的方法是使用枚举。

4 个答案:

答案 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等都是基于文本的。