我正在尝试用C编写一个简单的and服务器,到目前为止,我可以接收连接和接收完整的消息。但是,根据HTTP/1.0协议,当遇到"\r\n\r\n“序列时,我希望能够将信息发送回客户端。但是,当使用Telnet测试我的服务器时,当我输入"\r\n\r\n“时,服务器什么也不做,直到我在客户端点击"^]”。我在Apache上测试了这一点,Apache没有这个问题。所以我希望得到一些关于如何模仿Apache行为的信息。我的代码添加在下面,但请记住,我还没有接近完成,也没有实现很多错误检查。谢谢!
main(){
int sock_fd = 0;
int client_fd = 0;
struct sockaddr_in socket_struct;
/*Creates the socket*/
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
exit(EXIT_FAILURE);
}/*Ends the socket creation*/
/*Populates the socket address structure*/
socket_struct.sin_family = AF_INET;
socket_struct.sin_addr.s_addr=INADDR_ANY;
socket_struct.sin_port =htons(port);
if (bind(sock_fd, (struct sockaddr*) &socket_struct, sizeof(socket_struct)) < 0)
{
fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
exit(EXIT_FAILURE);
}//Ends the binding.
if (listen(sock_fd, 5) <0)
{
fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
exit(EXIT_FAILURE);
}//Ends the listening function
if ( (client_fd = accept(sock_fd, NULL, NULL)) <0)
{
fprintf(stderr, "%s: %s\n", getprogname(), strerror(errno));
exit(EXIT_FAILURE);
}//Ends the accepting.
while ( (size = read(client_fd, msg, 1024)) > 0)
{
//size = recv(client_fd, msg, 1024, MSG_PEEK|MSG_WAITALL);
if ( (msg[size-4] == 13) && (msg[size-3] == 10)&&(msg[size-2] == 13) && (msg[size-1] == 10) )
{
char* buffer = (char *)malloc(sizeof("The msg was: ")+ sizeof(msg));
sprintf(buffer, "The msg was: %s", msg);
send(client_fd, buffer, sizeof("The msg was: ")+ sizeof(msg), MSG_OOB);
}
}//ends the while loop for receiving data
close(client_fd);
}发布于 2012-10-28 04:09:27
首先,这行代码行不通:
while ( (size = read(client_fd, msg, 1024)) > 0)这将接收消息块,并且您收到的每个块都将覆盖最后一个块。这样做:
char msg[1024];
size_t pos = 0;
while (1) {
assert(pos < sizeof(msg));
ssize_t amt = read(client_fd, msg + pos, sizeof(msg) - pos);
if (amt < 0)
err(1, "read failed");
if (amt == 0)
break; // EOF
pos += amt;
char *e = strstr(msg, "\r\n\r\n");
if (e) {
size_t msglen = e - msg;
/* Handle a complete message here */
}
}这样,当您收到消息块时,它们就会写入您的缓冲区。一旦有了"\r\n\r\n"序列,您就可以处理整个消息,即使您可能会得到它的块。
的重要教训:在TCP中,包边界和消息边界可能是完全不同的,您从read获得的大小也可能是不同的。您必须通过查看数据本身来查找消息的结尾,而不是查看从read()返回了多少数据( EOF除外,它在read()返回0时发出信号)。
脚注:我认为带外数据并不是你想的那样。
send(client_fd, buffer, sizeof("The msg was: ")+ sizeof(msg), MSG_OOB);带外数据是TCP的一个奇怪的特性,在现代协议中几乎肯定应该避免这种特性。它的实现因平台而异,仅发送一个字节的带外数据是安全的。
它被Telnet协议(以及建立在Telnet上的FTP )用于某些用途,但在HTTP中没有任何用途。
https://stackoverflow.com/questions/13103601
复制相似问题