我需要跨服务器发送文件,但我需要在响应中添加header
。我不知道如何解决这个问题,因为我可以将文件读入缓冲区并使用以下代码一次发送一个缓冲区:
while ((nread = read(in, buffer, sizeof(buffer))) > 0) {
void *p = buffer;
while (nread > 0) {
int nwritten = write(csfd, p, nread);
if (nwritten <= 0) {
perror("error while sending the file to the client");
close(in);
close(csfd);
}
nread -= nwritten;
p += nwritten;
}
}
close(in);
close(csfd);
但是由于我需要发送标头,我需要能够将第一个数据块发送为<HEADER>\r\n<DATA-1/33>
,然后对套接字的后续写入应该像<DATA-2/33>
,<DATA-3/33>
, <DATA-4/33>
等等。
因此,假设我在char header[] = "FOUND 43199 29-33\r\n"
中有一个标题,如何将该标题与文件中的第一个数据块一起发送?
也许我可以在复制标题后从数组中的稍后位置开始读取缓冲区?或者有更好的方法?
答案 0 :(得分:2)
我建议使用压缩结构或带有效负载部分的大缓冲区:
+------------------------------------+
| |
| +----------+----------+--------+ |
| | Header | Payload | Footer | |
| +----------+----------+--------+ |
| transmit buffer |
+------------------------------------+
您将发送传输缓冲区,但您可以更改标头,有效负载或页脚,而无需更改发送缓冲区的代码。
编辑1:实施
一种实现方法是使用结构:
struct Transmit_Buffer
{
Header m_header;
uint8_t m_payload[PAYLOAD_CAPACITY];
Footer m_footer;
};
另一种实现是字节数组(uint8_t
):
uint8_t transmit_buffer[HEADER_SIZE + PAYLOAD_CAPACITY + FOOTER_SIZE];
您可以按索引参考各个部分:
const unsigned int header_index = 0U;
const unsigned int payload_begin = header_index + HEADER_SIZE;
const unsigned int footer_begin = payload_begin + PAYLOAD_CAPACITY;
使用该结构将是:
Transmit_Buffer buffer;
Send_Data((uint8_t *) &buffer, sizeof(Transmit_Buffer));
使用数组:
Send_Data(&transmit_buffer[0], sizeof(transmit_buffer));
要更改有效负载,您只能访问有效负载部分:
uint8_t * p_payload = &transmit_buffer[payload_begin];
或者
buffer.m_payload
在这种设计中,传输功能并不关心缓冲区中的内容,它的目的是传输数据。
您可以添加另一个创建页眉和页脚部分的图层,然后传输数据。在这种情况下,有效载荷无关紧要,因为它只是简单,无聊的数据。
因此,如果页眉和页脚相同,您可以编写有效负载部分,然后传输缓冲区。
答案 1 :(得分:2)
只需通过套接字发送标头,然后发送有效负载。
如果您担心您的客户必须进行两次阅读而不是一次阅读,并且您有点依赖于必须执行一次阅读,请尽快重写您的客户,因为 TCP不是数据包协议,它是一种不保留应用程序定义边界的流协议。您应该以这样的方式对客户端进行编码,即使一次接收一个字节也是如此。您必须使用有状态解析器,不要假设客户端能够立即read()
整个消息,并且不要指望保留发送方边界。
这意味着你的标题应该包含有效负载的长度,或者你应该有一个页脚(但在这种情况下,你必须在有效负载中转义这样的结束序列,这有点不方便)。 / p>
您无法使用不同的write()
调用来强制执行应用程序级框架!