我用C语言实现了基本的Web服务器,它提供来自客户端的GET请求.问题是它不发送HTML页面.
while(1){
if((temp_sock[id] = accept(sockfd, (t_sockaddr*)address, &address_size))==-1){
perror("Accepting Failure: ");
pthread_mutex_lock(&lock);
fprintf(logfile, "Accepting error: %d\n", localfd);
pthread_mutex_unlock(&lock);
exit(1);
}
else{
pthread_mutex_lock(&lock);
fprintf(logfile, "\nAccepting Success");
pthread_mutex_unlock(&lock);
}
if (temp_sock[id]> 0){
pthread_mutex_lock(&lock);
fprintf(logfile, "\nClient is connected");
pthread_mutex_unlock(&lock);
}
recv(temp_sock[id] , buf, buffsize, 0);
pthread_mutex_lock(&lock);
fprintf(logfile, "\nyou recieved : %s\n ", buf);
pthread_mutex_unlock(&lock);
if((resource=analyze(buf))==NULL){ /*analyze - implements basic security and searches files on a disc*/
printf("\nres is NULL");
write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
write(temp_sock[id], "Content-length: 50\n", 19);
write(temp_sock[id], "Content-Type: text/html\n\n", 25);
write(temp_sock[id], "<html><body><H1>404 Not Found</H1></body></html>", 50);
}
else{
while(fgets(message, 150, resource)!=NULL){
write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
write(temp_sock[id], "Content-length: 151\n", 19);
write(temp_sock[id], "Content-Type: text/html\n\n", 25);
write(temp_sock[id], message, 151); //here problems start
}
fclose(resource);
}
close(temp_sock[id]);
}
}
Run Code Online (Sandbox Code Playgroud)
这只是接受一个线程的循环,我不发布整个代码,因为一切正常,直到我想发送包含多行文本(例如维基百科文章)的页面后,它尝试读取文件网络服务器刚刚停止.但如果文件只包含
<html><body><H1>Hello! How are you?</H1></body></html>
Run Code Online (Sandbox Code Playgroud)
服务器以适当的方式发送它.提前致谢.
您的代码存在多个问题,但最严重的问题是:
while(fgets(message, 150, resource)!=NULL){
write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
write(temp_sock[id], "Content-length: 151\n", 19);
write(temp_sock[id], "Content-Type: text/html\n\n", 25);
write(temp_sock[id], message, 151); //here problems start
}
Run Code Online (Sandbox Code Playgroud)
fgets()只能在字符串上正常工作.读取二进制数据(如图像)时,它会表现不正常.使用fread()代替; 你需要稍微重新排序参数.
HTTP中的响应行必须终止\r\n,而不仅仅是\n.(这不会导致您的问题,但无论如何您应该修复它.)
您发送的内容长度为151是假的.检查文件的实际大小(例如,使用fstat())并发送,或者根本不发送内容长度.这不是强制性的.
您的代码写的字节数多于读取的字节数.保存返回值fgets()并将其传递给write().
您的代码未检查返回值write().假设write()将始终写入您提供给它的所有数据是不安全的- 就像read()它可能执行部分写入或完全失败一样.
您的代码正在为其读取的每个数据块发送一组新的HTTP标头.将该代码移到循环外部.