首页 > 试题广场 >

下面程序是利用winsock API编写的Web服务器程序

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

这道题你会答吗?花几分钟告诉大家答案吧!