【问题标题】:Soft terminating a simple webserver软终止一个简单的网络服务器
【发布时间】:2013-08-30 12:49:54
【问题描述】:

我正在构建自己的网络服务器。目前,我的极简代码是:

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>

#define SERVER_PORT 80

int main () {

    int nReqSocketId, nReqSize = 1024, nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
    char *sRequest = malloc(nReqSize);
    socklen_t nAddrLen;
    struct sockaddr_in oAddress;

    oAddress.sin_family = AF_INET;
    oAddress.sin_addr.s_addr = INADDR_ANY;
    oAddress.sin_port = htons(SERVER_PORT);

    if (nMainSocketId == 0) {
        fprintf(stderr, "Error during the creation of the socket\n");
        return 1;
    }

    if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress))) {
        fprintf(stderr, "The port %d is busy\n", SERVER_PORT);
        close(nMainSocketId);
        return 1;
    }

    printf("HTTP server listening on port %d\n", SERVER_PORT);

    while (1) {

        if (listen(nMainSocketId, 10) < 0) {
            perror("server: listen");
            close(nMainSocketId);
            exit(1);
        }

        nReqSocketId = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);

        if (nReqSocketId < 0) {
            perror("server: accept");
            close(nMainSocketId);
            exit(1);
        }

        recv(nReqSocketId, sRequest, nReqSize, 0);

        if (nReqSocketId > 0){
            printf("The Client is connected...\n\n%s\n", sRequest);
        }

        write(nReqSocketId, "HTTP/1.1 200 OK\n", 16);
        write(nReqSocketId, "Content-length: 50\n", 19);
        write(nReqSocketId, "Content-Type: text/html\n\n", 25);
        write(nReqSocketId, "<html><body><h1>Hello world!!!</h1></body></html>\n", 50);
        close(nReqSocketId);

    }

    printf("Goodbye!\n");

    close(nMainSocketId);

    return 0;

}

我可以创建一个“软关闭机制”让网络服务器打印“再见!”位于无限循环之后的短语?例如,当我输入“q”字母时……

【问题讨论】:

  • 您想从服务器的终端窗口或从客户端请求软终止它? (或两者兼而有之?)前者高度特定于操作系统,因为您不能在 nx 和 Windows 上以相同的方式在终端上等待。后者就像解析 HTTP 请求一样简单。
  • Ctrl + C 和 SIGINT 的处理程序。
  • @Medinoc 我想从我的 linux 服务器的终端窗口软终止它!
  • @someuser Ctrl + C 在 printf("Goodbye!\n");
  • @user2732907 这就是为什么 Medinoc 说“和 SIGINT 的处理程序”。为 SIGINT 安装一个信号处理程序,将 volatile 整数设置为零,并让该 volatile 整数成为循环的控制表达式。

标签: c sockets webserver


【解决方案1】:

为什么不消除所有这些写函数而只使用一个 send()?

您需要做的就是将您的响应存储在缓冲区中,然后发送缓冲区:

// Global
#define MAX 2048
char response[MAX]; // No need for char* 

// In Main
memset(response, 0, MAX); // **EDIT**
strcpy(response, "HTTP/1.1 200 OK\n");
strcat(response, "Content-length: 50\n");
strcat(response, "Content-Type: text/html\n\n");
strcat(response, "<html><body><h1>Hello world!!!</h1></body></html>\n");

// Now simply send the whole response in one go:
send(nReqSocketId, response, strlen(response), 0);

此外,您也可以像这样简单地将其设为非持久连接:

// Global
#define MAX 2048
char response[MAX];  // No need for char* 

// In Main
memset(response, 0, MAX); // **EDIT**
strcpy(response, "HTTP/1.1 200 OK\n");
strcat(response, "Content-Type: text/html\n\n");
strcat(response, "<html><body><h1>Hello world!!!</h1></body></html>\n");

// Now simply send the whole response in one go again:
send(nReqSocketId, response, strlen(response), 0);

// Shutdown the socket so it cannot write anymore:
shutdown(nReqSocketId,1);

// Then totally close it when you are ready:
close(nReqSocketId);

后者可能更适合您当前的工作;因为无论如何您都没有在网络服务器中保持多个连接。

一旦您关闭服务器端的连接,客户端(即网络浏览器)就会知道停止期待内容并正确完成工作。

希望这会有所帮助。

干杯!

PS-

当然,这是对您在此线程中的最后一个问题的回答,而不是软终止部分。

我还必须建议您使用 memset(response, 0, MAX) 以便每次响应时都有一个干净的状态。

【讨论】:

    【解决方案2】:

    在 *IXish 操作系统下,信号会唤醒某些阻塞系统调用并让它们返回。

    它们将指示错误并将errno 设置为EINTR。您可以使用这些机制来优雅地关闭服务器。

    请参阅您答案中的代码,在下面稍作调整/更正:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <signal.h>
    #include <unistd.h>
    #include <errno.h>
    
    #define SERVER_PORT 8080 /* Using a port>1024 one does not need to run this as root. */
    
    void onInt()
    {
      /* Do nothing. */
    }
    
    void onQuit()
    {
      /* Do nothing. */
    }
    
    int main()
    {
      int nMainSocketId = -1, nReqSocketId = -1;
      size_t nReqSize = 1024;
      char * sRequest = malloc(nReqSize); /* TODO: add error checking */
      socklen_t nAddrLen;
      struct sockaddr_in oAddress = {0};
    
      signal(SIGINT, onInt); /* TODO: add error checking */
      signal(SIGQUIT, onQuit); /* TODO: add error checking */
    
      printf("\n  W E L C O M E!\n\nPress CTRL-C or CTRL-\\ to quit.\n");
    
      oAddress.sin_family = AF_INET;
      oAddress.sin_addr.s_addr = INADDR_ANY;
      oAddress.sin_port = htons(SERVER_PORT);
    
      nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
      if (nMainSocketId < 0) /* 0 is a valid file/socket descriptor! */
      {
        perror("server: socket() failed");
        return 1;
      }
    
      if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress)))
      {
        perror("server: bind() failed");
        close(nMainSocketId);
        return 1;
      }
    
      printf("HTTP server listening on port %d\n", SERVER_PORT);
    
      while (1)
      {
        int result = 0;
    
        if (listen(nMainSocketId, 10) < 0)
        {
          perror("server: listen() failed");
          close(nMainSocketId);
          return 1;
        }
    
        result = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);
        if (result < 0)
        {
          if (EINTR == errno)
          {
            printf("Shutdown requested. Exiting ...\n");
            break;
          }
    
          perror("server: accept failed()");
          close(nMainSocketId);
          return 1;
        }
    
        nReqSocketId = result;
    
        result = recv(nReqSocketId, sRequest, nReqSize, 0); /* TODO: Check wether the request size was really read! */
        if (result < 0)
        {
          perror("server: recv() failed");
          close(nMainSocketId);
          return 1;
        }
        else if (result == 0)
        {
          printf("The client is disconnected. Waiting for another connection ...\n");
          close(nReqSocketId);
          nReqSocketId = -1;
          continue;
        }
    
        printf("The client is connected...\n\n%s\n", sRequest);
    
        /* TODO: add error checking for ALL write()s */
        write(nReqSocketId, "HTTP/1.1 200 OK\n", 16);
        write(nReqSocketId, "Content-length: 50\n", 19);
        write(nReqSocketId, "Content-Type: text/html\n\n", 25);
        write(nReqSocketId, "<html><body><h1>Hello world!!!</h1></body></html>\n", 50);
    
        close(nReqSocketId);
        nReqSocketId = -1;
      }
    
      printf("Goodbye!\n");
    
      close(nMainSocketId);
    
      return 0;
    }
    

    请注意,对recv() 的调用也可能会阻塞等待数据,然后由于SIGINT 被中断。因此,检查accept() 的结果时所做的相同逻辑应该应用于recv()

    【讨论】:

      【解决方案3】:

      @熊猫搜宝

      我使用 fprintf() 和文件描述符一起删除了 write(),我认为这是最好的方法,因为不需要 strlen()...看下面的代码:

      #include <stdio.h>
      #include <netinet/in.h>
      #include <signal.h>
      
      #define REQUEST_SIZE 1024
      #define SERVER_PORT 80
      
      int bExiting, nMainSocketId;
      
      void terminateServer () {
          if (bExiting) { return; }
          printf("\n\nTerminating server...\n");
          close(nMainSocketId);
          bExiting = 1;
      }
      
      int main () {
      
          int nRecvResult = -1, nReqSocketId = -1;
          char sRequest[REQUEST_SIZE];
          socklen_t nAddrLen;
          struct sockaddr_in oAddress;
          FILE *nRespFD;
      
          printf("\n  W E L C O M E!\n\nPress CTRL-C or CTRL-\\ to quit.\n");
      
          signal(SIGINT, terminateServer);
          signal(SIGQUIT, terminateServer);
      
          oAddress.sin_family = AF_INET;
          oAddress.sin_addr.s_addr = INADDR_ANY;
          oAddress.sin_port = htons(SERVER_PORT);
      
          nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
      
          if (nMainSocketId < 0) {
              perror("server: socket() failed");
              return 1;
          }
      
          if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress))) {
              perror("server: bind() failed");
              terminateServer();
              return 1;
          }
      
          printf("HTTP server listening on port %d\n", SERVER_PORT);
      
          while (bExiting == 0) {
      
              if (listen(nMainSocketId, 10) < 0) {
                  perror("server: listen() failed");
                  terminateServer();
                  return 1;
              }
      
              nReqSocketId = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);
      
              if (bExiting) { break; }
      
              if (nReqSocketId < 0) {
                  perror("server: accept() failed");
                  terminateServer();
                  return 1;
              }
      
              nRecvResult = recv(nReqSocketId, sRequest, REQUEST_SIZE, 0);
      
              if (nRecvResult < 0) {
                  perror("server: recv() failed");
                  terminateServer();
                  return 1;
              }
      
              if (nRecvResult == 0) {
                  printf("The client is disconnected. Waiting for another connection...\n");
                  close(nReqSocketId);
                  continue;
              }
      
              printf("The client is connected...\n\n%s\n", sRequest);
      
              nRespFD = fdopen(nReqSocketId, "a+");
      
              fprintf(nRespFD, "HTTP/1.1 200 OK\n");
              fprintf(nRespFD, "Content-length: 50\n");
              fprintf(nRespFD, "Content-Type: text/html\n\n");
              fprintf(nRespFD, "<html><body><h1>Hello world!!!</h1></body></html>\n");
      
              fclose(nRespFD);
      
              close(nReqSocketId);
      
          }
      
          printf("Goodbye!\n");
      
          return 0;
      
      }
      

      关于shutdown() 和close(),你能更好地解释一下区别吗?

      【讨论】:

      • shutdown() 只能阻止发送,只能阻止接收等,但实际上并没有关闭套接字,因此它的描述符仍然有效。 注意:当我第一次发帖时,我并没有考虑中断,我在想select。在 nx 上,您可以在 STDIN_FILENO 上使用它,因此您可以同时在终端和套接字上等待。有了这个,你甚至可以为你的服务器做一个完整的命令行解释器(允许你做各种事情,比如踢用户),而不仅仅是退出!
      • @Medinoc 谢谢你的解释!关于STDIN_FILENO,在终端和socket上同时等待是我想做的!!!你能发送一个最小的工作示例吗?
      【解决方案4】:

      好的,我的回复的第二部分解释了如何使您的网络服务器非持久化。顺便说一句,在 HTTP 1.1 之前,持久连接曾经被称为 Keep-Alive。由于我看到您每次发送后都会关闭响应套接字,因此您不妨将 Web 服务器设置为“非持久性”。

      这意味着您不必发送“Content-Length: X”,因为 shutdown()。您可以通过三种不同的方式关闭套接字:

      "The constants SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, respectively..."
      

      通过执行shutdown(SOCKET, 1),我们实际上是在向客户端(浏览器)发送一个FIN ack,让它知道套接字已完成写入。因此,无需设置“Content-Length: X”标头响应。

      现在,这不是 shutdown() VS close() 的事情。这是一个 shutdown() AND close() 的事情。您仍然必须关闭()套接字才能销毁它。关机不会为您做到这一点。

      总而言之,如果您不需要跟踪多个连接,请考虑从标头中取出“Content-Length:”。只需使用 shutdown(SOCKET, 1) 作为“传输结束”机制,然后关闭即可销毁套接字。

      /---------------------------------------------- -------------------------------------------------- ----------------------------------/

      至于创建一个完整的 FILE* 只是为了发送字符串文字,我不确定是否值得。你有没有把这个放在板凳上并得到一些结果?无论如何,如果您正在寻找性能,我知道 strcat() [当然包括 strlen()] 和 strlen() 的其他方法。我不知道是这种情况。

      PS-strcat() 在开始时非常快,只有在连接一个大缓冲区时它才开始增加其复杂性。查找 SIMD 以及如何根据您的架构优化这些类型的功能。

      【讨论】:

      • 感谢您对 shutdown() 的解释。关于 fprintf() + FILE*... 不知道是不是比 send() + strlen() 快:我只看到 fprintf() + FILE* 经常用在一些教学网络服务器示例中...
      【解决方案5】:

      同时等待标准输入和套接字

      这是一种特定于 POSIX 的行为,在 Windows 上明确不起作用。它依赖于这样一个事实:在 *n*x 平台上,套接字是文件描述符,并且它使用 select 函数。

      这是一个简化的函数,它包装了select 以等待单个套接字。

      /*Waits on a single socket and stdin.*/
      int waitOnStdinAndSocket(
       int sockFd,             /*[in] Socket descriptor*/
       int *pInputOnStdin,     /*[out] Set to a nonzero value if there is input on stdin*/
       int *pInputOnSocket,    /*[out] Set to a nonzero value if there is input on the socket*/
       sturct timeval *timeout /*[in/opt] Timeout*/
       ) /*Returns a negative value on failure.*/
      {
          int ret;
          fd_set fds;
      
          *pInputOnStdin = 0;
          *pInputOnSocket = 0;
      
          FD_ZERO(&fds);
          FD_SET(STDIN_FILENO, &fds);
          FD_SET(sockFd, &fds);
          ret = select(sockFd+1, &fds, NULL, NULL, timeout);
          if(ret >= 0)
          {
              *pInputOnStdin = FD_ISSET(STDIN_FILENO, &fds);
              *pInputOnSocket = FD_ISSET(sockFd, &fds);
          }
          return ret;
      }
      

      【讨论】:

        【解决方案6】:

        @Medinoc

        非常感谢!

        阅读您的回复后,我在网上尝试了一下,发现了这个 GNU 页面:http://www.gnu.org/software/libc/manual/html_node/Server-Example.html

        所以,经过一些尝试,我已经能够将所有东西与我的“hello world”示例集成在一起。结果如下:

        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <netinet/in.h>
        #include <string.h>
        
        #define SERVER_PORT 80
        #define REQUEST_MAX_SIZE 1024
        
        char sRequest[REQUEST_MAX_SIZE];
        int bListening = 1, nMainSocket;
        
        void terminateServer () {
            if (bListening == 0) { return; }
            printf("\n\nTerminating server...\n");
            close(nMainSocket);
            bListening = 0;
        }
        
        void switchStdin () {
            if (strcmp(sRequest, "q\n") == 0) {
                terminateServer();
            } else {
                printf("Unknown request %s\n", sRequest);
            }
        }
        
        void helloWorld (const int nRequestId) {
            printf("The client is connected...\n\n%s\n", sRequest);
                write(nRequestId, "HTTP/1.1 200 OK\n", 16);
                write(nRequestId, "Content-length: 50\n", 19);
                write(nRequestId, "Content-Type: text/html\n\n", 25);
                write(nRequestId, "<html><body><h1>Hello world!!!</h1></body></html>\n", 50);
        }
        
        int main (void) {
        
            int nOldReqSock, nNewReqSock, nReqLen, nUninitLen = REQUEST_MAX_SIZE;
            fd_set oActiveFD, oReadFD;
            socklen_t nAddrLen;
            struct sockaddr_in oAddress;
        
            oAddress.sin_family = AF_INET;
            oAddress.sin_addr.s_addr = INADDR_ANY;
            oAddress.sin_port = htons(SERVER_PORT);
        
            /* Create the socket and set it up to accept connections. */
        
            nMainSocket = socket(AF_INET, SOCK_STREAM, 0);
        
            if (nMainSocket < 0) {
                perror("socket");
                return 1;
            }
        
            if (bind(nMainSocket, (struct sockaddr *) &oAddress, sizeof(oAddress))) {
                perror("bind");
                terminateServer();
                return 1;
            }
        
            if (listen(nMainSocket, 10) < 0) {
                perror("listen");
                terminateServer();
                return 1;
            }
        
            /* Initialize the set of active sockets plus STDIN. */
        
            FD_ZERO(&oActiveFD);
            FD_SET(STDIN_FILENO, &oActiveFD);
            FD_SET(nMainSocket, &oActiveFD);
        
            printf("\n  W E L C O M E!\n\nType \"q\" to quit.\n");
        
            while (bListening) {
        
                /* Block until input arrives on one or more active sockets. */
        
                oReadFD = oActiveFD;
        
                if (select(FD_SETSIZE, &oReadFD, NULL, NULL, NULL) < 0) {
                    perror("select");
                    terminateServer();
                    return EXIT_FAILURE;
                }
        
                /* Service all the sockets with input pending. */
        
                for (nOldReqSock = 0; bListening && nOldReqSock < FD_SETSIZE; ++nOldReqSock) {
        
                    if (FD_ISSET(nOldReqSock, &oReadFD)) {
        
                        if (nOldReqSock == nMainSocket) {
        
                            /* Connection request on original socket. */
        
                            nAddrLen = sizeof(oAddress); /* why??? */
                            nNewReqSock = accept(nMainSocket, (struct sockaddr *) &oAddress, &nAddrLen);
        
                            if (nNewReqSock < 0) {
                                perror("accept");
                                terminateServer();
                                return EXIT_FAILURE;
                            }
        
                            FD_SET(nNewReqSock, &oActiveFD);
        
                        } else {
        
                            /* Data arriving on an already-connected socket. */
        
                            nReqLen = read(nOldReqSock, sRequest, REQUEST_MAX_SIZE);
        
                            if (nReqLen < 0) {
                                /* Read error. */
                                perror("read");
                                terminateServer();
                                return EXIT_FAILURE;
                            } else if (nReqLen == 0) {
                                /* End-of-file. */
                                printf("End-of-file\n");
                                close(nOldReqSock); /* why??? */
                                FD_CLR(nOldReqSock, &oActiveFD); /* why??? */
                                continue;
                            } else {
                                /* Data read. */
                                if (nUninitLen > nReqLen) { memset(sRequest + nReqLen, 0, nUninitLen - nReqLen); }
                                nUninitLen = nReqLen;
                            }
        
                            if (nOldReqSock == STDIN_FILENO) {
                                /* Standard input received */
                                switchStdin(nReqLen);
                            } else {
                                /* TCP/IP request received */
                                helloWorld(nOldReqSock);
                            }
        
                        }
        
                    } 
        
                }
        
            }
        
            printf("Goodbye\n");
        
            return 0;
        
        }
        

        我还在我不理解的行附近添加了一些/* why??? */ cmets。能否请您简要解释一下它们是什么?

        【讨论】:

          【解决方案7】:

          根据@Medinoc、@someuser 和@Elchonon 的建议,我按以下方式更正了我的代码:

          #include <stdio.h>
          #include <stdlib.h>
          #include <netinet/in.h>
          #include <signal.h>
          
          #define SERVER_PORT 80
          
          int nStatus, nMainSocketId;
          
          void onInt () {
              printf("You have pressed CTRL-C.\n");
              nStatus = 0;
              shutdown(nMainSocketId, 2);
          }
          
          void onQuit () {
              printf("You have pressed CTRL-\\.\n");
              nStatus = 0;
              shutdown(nMainSocketId, 2);
          }
          
          int main () {
          
              int nReqSocketId, nReqSize = 1024;
              nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
              char *sRequest = malloc(nReqSize);
              socklen_t nAddrLen;
              struct sockaddr_in oAddress;
          
              signal(SIGINT, onInt);
              signal(SIGQUIT, onQuit);
              oAddress.sin_family = AF_INET;
              oAddress.sin_addr.s_addr = INADDR_ANY;
              oAddress.sin_port = htons(SERVER_PORT);
              nStatus = 1;
          
              printf("\n  W E L C O M E!\n\nPress CTRL-C or CTRL-\\ to quit.\n");
          
              if (nMainSocketId == 0) {
                  fprintf(stderr, "Error during the creation of the socket\n");
                  return 1;
              }
          
              if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress))) {
                  fprintf(stderr, "The port %d is busy\n", SERVER_PORT);
                  close(nMainSocketId);
                  return 1;
              }
          
              printf("HTTP server listening on port %d\n", SERVER_PORT);
          
              while (nStatus) {
          
                  if (listen(nMainSocketId, 10) < 0) {
                      perror("server: listen");
                      close(nMainSocketId);
                      return 1;
                  }
          
                  nReqSocketId = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);
          
                  if (nReqSocketId < 0) {
                      perror("server: accept");
                      close(nMainSocketId);
                      return 1;
                  }
          
                  recv(nReqSocketId, sRequest, nReqSize, 0);
          
                  if (nReqSocketId > 0){
                      printf("The Client is connected...\n\n%s\n", sRequest);
                  }
          
                  write(nReqSocketId, "HTTP/1.1 200 OK\n", 16);
                  write(nReqSocketId, "Content-length: 50\n", 19);
                  write(nReqSocketId, "Content-Type: text/html\n\n", 25);
                  write(nReqSocketId, "<html><body><h1>Hello world!!!</h1></body></html>\n", 50);
                  close(nReqSocketId);
          
              }
          
              printf("Goodbye!\n");
          
              close(nMainSocketId);
          
              return 0;
          
          }
          

          进程软终止,现在!!但是,不幸的是,套接字没有! :( ...所以每当我按下 CTRL-C 或 CTRL-\ 以退出时,我都会收到以下消息:

          server: accept: Invalid argument
          

          有什么解决办法吗?

          编辑

          @alk

          感谢您的回答!您建议我使用另一种方法来软终止我的网络服务器...:

          #include <stdio.h>
          #include <stdlib.h>
          #include <netinet/in.h>
          #include <signal.h>
          
          #define SERVER_PORT 80
          
          int bExiting, nMainSocketId;
          
          void terminateServer () {
              if (bExiting) { return; }
              printf("\n\nTerminating server...\n");
              close(nMainSocketId);
              bExiting = 1;
          }
          
          int main () {
          
              int nRecvResult = -1, nReqSocketId = -1;
              size_t nReqSize = 1024;
              char * sRequest = malloc(nReqSize);
              socklen_t nAddrLen;
              struct sockaddr_in oAddress = {0};
          
              printf("\n  W E L C O M E!\n\nPress CTRL-C or CTRL-\\ to quit.\n");
          
              signal(SIGINT, terminateServer);
              signal(SIGQUIT, terminateServer);
          
              oAddress.sin_family = AF_INET;
              oAddress.sin_addr.s_addr = INADDR_ANY;
              oAddress.sin_port = htons(SERVER_PORT);
          
              nMainSocketId = socket(AF_INET, SOCK_STREAM, 0);
          
              if (nMainSocketId < 0) {
                  perror("server: socket() failed");
                  return 1;
              }
          
              if (bind(nMainSocketId, (struct sockaddr *) &oAddress, sizeof(oAddress))) {
                  perror("server: bind() failed");
                  terminateServer();
                  return 1;
              }
          
              printf("HTTP server listening on port %d\n", SERVER_PORT);
          
              while (bExiting == 0) {
          
                  if (listen(nMainSocketId, 10) < 0) {
                      perror("server: listen() failed");
                      terminateServer();
                      return 1;
                  }
          
                  nReqSocketId = accept(nMainSocketId, (struct sockaddr *) &oAddress, &nAddrLen);
          
                  if (bExiting) { break; }
          
                  if (nReqSocketId < 0) {
                      perror("server: accept failed()");
                      terminateServer();
                      return 1;
                  }
          
                  nRecvResult = recv(nReqSocketId, sRequest, nReqSize, 0);
          
                  if (nRecvResult < 0) {
                      perror("server: recv() failed");
                      terminateServer();
                      return 1;
                  }
          
                  if (nRecvResult == 0) {
                      printf("The client is disconnected. Waiting for another connection...\n");
                      close(nReqSocketId);
                      continue;
                  }
          
                  printf("The client is connected...\n\n%s\n", sRequest);
          
                  /* This is only a simple "Hello world"... */
                  write(nReqSocketId, "HTTP/1.1 200 OK\n", 16);
                  write(nReqSocketId, "Content-length: 50\n", 19);
                  write(nReqSocketId, "Content-Type: text/html\n\n", 25);
                  write(nReqSocketId, "<html><body><h1>Hello world!!!</h1></body></html>\n", 50);
          
                  close(nReqSocketId);
          
              }
          
              free(sRequest);
              printf("Goodbye!\n");
          
              return 0;
          
          }
          

          你怎么看?我应该添加一些东西吗?

          不过,我还有一个问题。我可以将 fprintf() 与文件描述符结合使用来替代 write() 吗?还有……怎么做?

          【讨论】:

          • 您打算在哪个操作系统上运行它?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-14
          • 2010-10-21
          • 2016-05-18
          • 1970-01-01
          • 1970-01-01
          • 2011-01-13
          相关资源
          最近更新 更多