【问题标题】:Adding custom message header添加自定义消息头
【发布时间】:2012-03-19 21:36:54
【问题描述】:

谁能告诉我:“如何构建标题?”我正在编写一个 FTP 客户端-服务器代码。我想在客户端为我必须发送到服务器的所有数据包添加一个标头,其中包含我的数据大小等信息。

我在 SO 看到了一些示例,但无法弄清楚确切的方法。 任何指向示例/示例代码的指针都将不胜感激。

【问题讨论】:

    标签: c++ windows sockets header ftp-client


    【解决方案1】:

    查看 scapy,一个用于构建数据包的库。我认为这是您需要的。

    【讨论】:

    • 我在使用 C++ 的 Windows 平台上。我需要简单的“结构”代码来制作我的标题和一些关于如何将它们附加到我的原始数据并将它们发送到服务器的信息。
    • 啊,那没关系。应该先问“哪种语言”。如果您自己实现 FTP 协议,请查看 ftp 规范,它会告诉您需要在标头中包含什么。然后,您需要一个允许您发送您构建的数据包的低级库。
    • 如果你更清楚地表达你的问题,你可能会得到更多的答案。
    【解决方案2】:

    建立协议数据的最佳方法是在某处有一个uint8_t 的缓冲区,并按照协议中的规定填充它。

    对于 FTP 来说,这相当简单,因为控制连接中只有 ASCII 字符串。这样的事情可能会奏效:

    bool append_literal(uint8_t **cursor, uint8_t *end, uint8_t const *data, size_t size) {
        assert(cursor);
        assert(*cursor);
        assert(end);
        assert(*cursor < end);
        assert(data);
        if((end - *cursor) < size)    // Check buffer limit
            return false;
        memcpy(*cursor, data, size);  // Copy
        *cursor += size;              // Increment cursor
        return true;
    }
    
    bool append_number(uint8_t **cursor, uint8_t *end, uint64_t number) {
        assert(cursor);
        assert(*cursor);
        assert(end);
        assert(*cursor < end);
        if((end - *cursor) < 17)     // Max number of base 10 digits in uint64_t
            return false;
        *cursor += sprintf(*cursor, "%" PRIu64, number);
        return true;
    }
    
    bool append_uint32_binary(uint8_t **cursor, uint8_t *end, uint32_t value) {
        assert(cursor);
        assert(*cursor);
        assert(end);
        assert(*cursor < end);
        if((end - *cursor) < 4)      // Bytes needed for uint32 value
            return false;
        *(*cursor)++ = (value >> 24) & 0xff;
        *(*cursor)++ = (value >> 16) & 0xff;
        *(*cursor)++ = (value >> 8) & 0xff;
        *(*cursor)++ = value & 0xff;
        return true;
    }
    
    // Specific FTP commands
    bool append_size_command(uint8_t **cursor, uint8_t *end, uint64_t size) {
        return append_literal(cursor, end, "SIZE ", 5) &&
            append_number(cursor, end, size) &&
            append_literal(cursor, end, "\r\n", 2);
    }
    // [...]
    
    bool send_size_command(int fd, uint64_t size) {
        uint8_t buffer[32];
        uint8_t *cursor = buffer;
        uint8_t *const end = buffer + sizeof buffer;
        if(!append_size_command(&cursor, end, size))
            return false;
        size_t length = cursor - buffer;
        ssize_t sent = send(fd, buffer, length, 0);
        return (sent == length);
    }
    

    “assert”语句测试如果您的程序编写正确(即指针是否有效)将始终为真的事情。任何函数在成功时返回true,如果失败则返回false

    我已经为套接字使用了标准的 POSIX 函数,因为 WinSock 实现了这些函数,而且它们相当便携。

    你的作业是找到你需要为PRIu64 包含的标题:)

    【讨论】:

    • 谢谢你的回复,但我之前问了一个错误的问题:-(我现在已经编辑了。我很抱歉。
    • 我想为所有数据包添加一个标头,其中包含数据大小等详细信息,然后使用recv将它们发送到服务器。你能帮帮我吗?
    • 我添加了一个函数来将一个 uint32 值作为二进制数据添加到输出缓冲区;您可以使用这些函数来构造标题。
    【解决方案3】:

    定义一个结构,其中包含您希望在两个客户端-服务器的 Header 中的成员(最好在两者中都包含一个带有结构的 Header 文件)。在原始消息之前发送标头。在服务器端接收结构体的固定长度参数。

    typedef struct  
    {
        DWORD   dwMsgType ; 
        DWORD   dwMsgSize ;
    }MSG_HEADER, *PMSG_HEADER ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多