【发布时间】:2012-03-19 21:36:54
【问题描述】:
谁能告诉我:“如何构建标题?”我正在编写一个 FTP 客户端-服务器代码。我想在客户端为我必须发送到服务器的所有数据包添加一个标头,其中包含我的数据大小等信息。
我在 SO 看到了一些示例,但无法弄清楚确切的方法。 任何指向示例/示例代码的指针都将不胜感激。
【问题讨论】:
标签: c++ windows sockets header ftp-client
谁能告诉我:“如何构建标题?”我正在编写一个 FTP 客户端-服务器代码。我想在客户端为我必须发送到服务器的所有数据包添加一个标头,其中包含我的数据大小等信息。
我在 SO 看到了一些示例,但无法弄清楚确切的方法。 任何指向示例/示例代码的指针都将不胜感激。
【问题讨论】:
标签: c++ windows sockets header ftp-client
查看 scapy,一个用于构建数据包的库。我认为这是您需要的。
【讨论】:
建立协议数据的最佳方法是在某处有一个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 包含的标题:)
【讨论】:
定义一个结构,其中包含您希望在两个客户端-服务器的 Header 中的成员(最好在两者中都包含一个带有结构的 Header 文件)。在原始消息之前发送标头。在服务器端接收结构体的固定长度参数。
typedef struct
{
DWORD dwMsgType ;
DWORD dwMsgSize ;
}MSG_HEADER, *PMSG_HEADER ;
【讨论】: