【问题标题】:C: Sending a RPC Method name + ArgumentsC:发送 RPC 方法名称 + 参数
【发布时间】:2015-05-01 14:38:23
【问题描述】:

我希望发送一个 RPC,在本例中是一个 char 数组,其中包含要执行的函数的名称和参数列表。

参数是整数。

例子:

Function name: plus
argument 1: 19
argument 2: 23

我想做的是按顺序构造一个包含每个数组的数组:

  1. 函数名大小的八进制值(在本例中为 4)
  2. 字符'p', 'l', 'u', 's'
  3. 第一个参数大小的八进制值(在本例中为 2,因为 '1', '9')
  4. 字符“1”和字符“9”
  5. 第二个参数大小的八进制值(在本例中为 2,因为 '2', '3')
  6. char '2' 和 char '3'

那么,我需要压缩

我已经有了这个编码为八进制值的函数:

int decimalToOctal(int n) {
  int rem, i = 1, octal = 0;
  while (n != 0) {
    rem = n % 8;
    n/=8;
    octal += rem*i;
    i *= 10;
  }

  return octal;
}

但我不知道如何将八进制值和字符压缩到一个需要通过套接字发送的数组中。或者可能我需要另一种类型的数组?感谢您的任何提示。

【问题讨论】:

  • 不相关,但为了提高效率,将所有内容视为二进制数据,不要发送 19,而是 10011,发送“+”而不是“加号”。

标签: c arrays function rpc remote-access


【解决方案1】:

听 Benjy,你可以发挥创意。为什么不尝试使用位域或将所有内容打包到 char 中。

struct packet 
{
    int num  : 3;
    int      : 1;
    int func : 4;
};

所以这里你有你的八进制数、一个填充位和 4 位来表示一些东西。当然它不会是完整的 ASCII 表。制作自己的数据包。

【讨论】:

    【解决方案2】:

    “如何通过网络发送信息并保持兼容”并不是一个新问题。 您可能认为发送一些结构或数组是一个不错的想法 - 但是许多编译器在每个成员之间放置了额外的字节以使多余的时间更快。 因此,您可能希望以某种文本形式发送数据并根据某些关键字天真地拆分它。如果其中一个关键字本身就是一个有效的参数,那么会发生什么?例如,您可能希望拆分找到字符串function: 的文本。那么如果发送char[] 类型的参数和值I'm a math student and function: 会发生什么?你完蛋了。

    这就是我建议的原因 - 使用 JSON 或 XML(我会继续使用 JSON,因为它更小且更具可读性)。你有很多 C-JSON 库。您只需定义某种形式的 JSON,客户端和服务器都可以像这样解析和发送所有内容。例如:

    {
    "function":"plus",
    "arguments":[1,2]
    }
    

    许多低级开发人员可能讨厌在 C 中使用 javascript 概念的想法,但实际上,当您考虑它时 - 这是一个非常聪明的解决方案。 首先,明天您的客户端或服务器可以用与 C 不同的语言编写,然后您就不能再发送任何结构了。每种体面的语言都有 JSON 库。此外,JSON 成为最流行的数据交换结构之一。

    【讨论】:

      【解决方案3】:

      正如前面的答案所提到的,您需要创建一个数据包来序列化并通过网络发送。

      因此,下面的示例适用于 DGRAM 套接字,但也适用于 STREAM 套接字的一些更改

      第一步创建您自己的数据包。例如:

       typedef struct messageInfo
       {
           char clientReq[MAX_LENGTH];
           u_int32_t arg;
           u_int32_t value;
           //maybe add arglist // maybe send less data by encoding 
           /* required in case of unreliable connection for end     packet***u_int16_t end;*** */ 
       }__attribute__ ((__packed__))info;  
      

      第二步通过套接字伪代码发送它。

      fd = socket( family, TYPE, 0 ); //TYPE = SOCK_STREAM or SOCK_DGRAM
      //bind locally
      //update peer sock structure to sendto or write
      //create header start
      uint8_t *tBuf = malloc(sizeof (info)); 
      //memset to zero
      info *pHeader = (info *)tBuf;
      pHeader->value = htonl(19); //local value to send
      pHeader->clientReq  = "plus";
      pheader->arg = htonl(23);
      //create header end
      //send to receiver
      sendto(serverSock, tBuf, sizeof(info),0
                                   ,(struct sockaddr *) &peerV4,
                                   sizeof(peerV4));
      

      第三步接收伪代码

       //create fd and init
       //recvfrom allocate buffer to recv
       uint8_t *recvBuf = malloc(sizeof(info));
       info *pheader = (info *)recvBuf;
       int currLen = recvfrom( fd, recvBuf,
                    sizeof(info),0,(struct sockaddr *)&peerV4,
                       &sockaddrLen);
        //error handling
        if(currLen == sizeof(info))
        {
      
             //close socket if end is specified in case of connection less protocol
             // strcpy to localRecv
             char *localRecv = malloc(MAX_LENGTH);
             strcpy (localRecv,pheader->clientReq);
             //do something with the values on the server like
             if (strcasecmp(localRecv,"plus")     == 0) //pseudo
                  plus(ntohl(pheader->arg),ntohl(pheader->value));
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-01
        • 2014-05-16
        • 2015-10-01
        • 2014-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-09
        相关资源
        最近更新 更多