下面程序是利用winsock API编写的Web服务器程序
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h
#define BUF_SIZE 80
#define HOSTNAME "localhost"
#define PORT 80
char buffer[BUF_SIZE];
void finish(int code)
{
if ( WSACleanup() == SOCKET_ERROR ) {
fprintf(stderr, "Encounter error while clean up WinSock.\n");
code = 1;
}
exit(code);
}
int main(int argc, char *argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
SOCKET socket1, socket2;
struct sockaddr_in server1, client1;
struct hostent *hp;
signed long int len, count = 0;
char path[255], root[255], temp[255];
char response[1024];
char line[1024];
int pos;
FILE *stream1;
int readcount;
// 处理参数
if ( argc < 2 ) {
strcpy(root, ".\\");
printf("The current directory is used as the root directory of document.\n");
} else {
strcpy(root, argv[1]);
printf("%s is used as root directory.\n", root);
}
// 初始化Winsock
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
fprintf(stderr, "Could not find a usable WinSock DLL.\n");
finish(1);
}
/* The WinSock DLL is acceptable. Proceed. */
// 建立套接字描述符
if ( (socket1 = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET ) {
fprintf(stderr, "Encountered error while create a new socket.\n");
finish(1);
}
// 获得主机host信息
if ( (hp = gethostbyname(HOSTNAME)) == NULL ) {
fprintf(stderr, "Encountered error while get host IP address.\n");
finish(1);
}
server1.sin_family = AF_INET;
server1.sin_port = htons(PORT);
memcpy((char *)&server1.sin_addr, (char *)hp->h_addr, hp->h_length);
// 绑定地址信息
if ( bind(socket1, (struct sockaddr *)&server1, sizeof(server1) ) == SOCKET_ERROR ) {
fprintf(stderr, "Encountered error while bind address infomation.\n");
finish(1);
}
// 设定socket1为监听状态
if ( listen(socket1, 5) == SOCKET_ERROR ) {
fprintf(stderr, "Encountered error while set to listen mode.\n");
finish(1);
}
// 监听端口信息,当有连接以后则对请求进行处理
do {
len = sizeof(client1);
printf("Accepting connections...\n");
socket2 = accept(socket1, (struct sockaddr*)&client1, (int *)&len);
if ( socket2 == INVALID_SOCKET ) {
fprintf(stderr, "Encountered error while accept connection.\n");
finish(1);
} else do {
err = recv(socket2, buffer, BUF_SIZE, 0);
for ( len = 0 ; len < err ; len ++ ) {
line[pos++] = buffer[len];
if ( buffer[len] == 0x0a && line[pos-2] == 0x0d ) { // 一行结束
line[pos-2] = '\0';
printf("%s\n", line);
if ( strlen(line) == 0 ) { // 输出结果
// 看路径指定的文件是否存在
strcpy(temp, root);
strcat(temp, path);
if ( (stream1 = fopen(temp, "r")) == NULL ) {
// 文件不存在
sprintf(response, "HTTP/1.1 404 File Not Found\n\n<html>File Not Found</html>\n");
if ( send(socket2, response, strlen(response), 0) == SOCKET_ERROR ) {
fprintf(stderr, "Encoutered error while send response.\n");
finish(1);
}
printf("File not found: %s\n", temp);
} else {
// 文件存在
sprintf(response, "HTTP/1.1 200 Success\n\n");
send(socket2, response, strlen(response), 0);
while(!feof(stream1)) {
readcount = fread(response, 1, 1024, stream1);
if ( send(socket2, response, readcount, 0) == SOCKET_ERROR ) {
fprintf(stderr, "Encoutered error while send response.\n");
fclose(stream1);
finish(1);
}
}
fclose(stream1);
}
// 关闭连接
closesocket(socket2); // 关闭socket2
}
if ( strstr(line, "GET ") == line) { // 获取路径
strcpy(path, strchr(line, ' ') + 1);
*(strchr(path, ' ')) = '\0';
while( strchr(path, '/') ) *(strchr(path, '/')) = '\\';
}
pos = 0;
}
}
} while ( err != 0 && err != SOCKET_ERROR)
} while(1);
finish(0);
return 0;
}
问题:
(1) 该程序在正确运行后阻塞在哪里?
(2) 一旦浏览器发出Http请求后,该服务器程序作了哪些处理?
(3) 如果该程序支持多用户并发访问,还需作哪些改进?画出改进后的算法流程
