下面程序是利用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) 如果该程序支持多用户并发访问,还需作哪些改进?画出改进后的算法流程