我需要跨服务器发送一个文件,但我需要在响应中添加一个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"中有一个头,如何将它与文件中的第一个数据块一起发送?
也许我可以在复制标头之后从数组的稍后位置开始读取到缓冲区?或者也许有更好的方法?
发布于 2015-06-02 15:14:29
我建议使用填充结构或带有有效负载部分的大型缓冲区:
+------------------------------------+
| |
| +----------+----------+--------+ |
| | 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在本设计中,传输函数不关心缓冲区中的内容,它的目的是传输数据。
您可以添加另一个层来创建页眉和页脚部分,然后传输数据。在这种情况下,有效载荷是无关紧要的,因为它只是简单、乏味的数据。
因此,如果页眉和页脚相同,则编写有效负载部分,然后传输缓冲区。
发布于 2015-06-02 15:35:11
只需发送标题,然后负载通过套接字。
如果您担心您的客户端将不得不进行两次读取而不是一次读取,并且您需要执行一次读取,请尽快重新工作您的客户端,因为TCP不是数据包协议,它是一种流协议,不保留应用程序定义的边界。您应该以这样一种方式编写客户端代码,即使一次只接收一个字节,它也能工作。您必须使用有状态解析器,不要假设客户端可以同时对整个消息进行read(),也不要期望发送方边界被保留。
这意味着您的页眉应该包含有效负载的长度,或者您应该有一个脚注(但在这种情况下,您必须在有效负载中转义这样的结束序列,这有点不方便)。
您不能使用不同的write() 调用来强制应用程序级别的框架!
https://stackoverflow.com/questions/30599795
复制相似问题