Linux C套接字 - 保持服务器活着

时间:2015-12-08 07:44:19

标签: c linux

我正在使用C来实现一个带有Linux套接字的简单客户端 - 服务器检索系统。我现在已成功连接远程服务器,但是当我关闭连接时,服务器关闭,即服务器程序停止。 我该怎么做才能避免这种情况?

这是我的代码示例:

服务器:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>

int main(void)
{
   int optval;
   socklen_t optlen = sizeof(optval);

   char str[100] = "";
   int listen_fd, conn_fd;
   struct sockaddr_in servaddr;

   listen_fd = socket(AF_INET, SOCK_STREAM, 0);

   // check if on
   getsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen);
   printf("keep alive is %s\n", (optval? "ON" : "OFF"));

   // set it on
   optval = 1;
   optlen = sizeof(optval);
   setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
   printf("done, check again.\n");

   printf("keep alive is %s\n", (optval? "ON" : "OFF"));

   bzero( &servaddr, sizeof(servaddr));

   // set appropriate protocol and port number (15792)
   // the htons() function converts the unsigned short integer
   // from host byte order to network byte order.
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = htons(INADDR_ANY);
   servaddr.sin_port = htons(15792);

   // Bind a name to a socket
   bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));

   // listening for incoming connection
   listen(listen_fd, 10);

   // accept a connection on a socket
   conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);

   do
   {

      // set str to null
      bzero(str, 100);


      // Read from a file descriptor (linux all)
      read(conn_fd,str,100);

      // print the received message
      // printf("Received: %s\n",str);

      if (!strcmp(str, "GET TIME\n"))
      {
         bzero(str, 100);

         time_t clocks;
         clocks = time(NULL);
         sprintf(str, "%s", ctime(&clocks));
         write(conn_fd, str, strlen(str));
         //close(conn_fd);
      }
      else
      {
         bzero(str, 100);
         strcpy(str, "ERROR: No such command.\n");
         write(conn_fd, str, strlen(str));
         //close(conn_fd);
      }
   } while (1);
}

客户端:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char **argv)
{
   // declare necessary variables
   int sockfd;
   char recv[1024] = "";
   char command[100] = "";
   struct sockaddr_in servaddr;

   if (argc != 2)
   {
      printf("usage: %s <ip address>\n", argv[0]);
      exit(EXIT_FAILURE);
   }


      // create a socket with the appropriate protocol
      if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
      {
         printf("ERROR: Failed create cosket.\n");
         exit(EXIT_FAILURE);
      }

      // Set all the socket structures with null values.
      bzero(&servaddr, sizeof servaddr);

      // set appropriate protocol and port number (1999)
      // The htons() function converts the unsigned short integer 
      // hostshort from host byte order to network byte order.
      servaddr.sin_family = AF_INET;
      servaddr.sin_port = htons(15792);

      // Convert IPv4 and IPv6 addresses from text to binary form
      if (inet_pton(AF_INET, argv[1], &(servaddr.sin_addr)) <= 0)
      {
         printf("ERROR: Wrong ip address.\n");
         exit(EXIT_FAILURE);
      }

      // attempt to connect to a socket
      if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
      {
         printf("ERROR: Failed at connect.\n");
         exit(EXIT_FAILURE);
      }
      else
      {
         printf("------ connect successfull ------\n");
      }

   do
   {

      printf("> ");
      fgets(command, 100, stdin);
      write(sockfd, command, strlen(command));

      if (!strcmp(command, "QUIT\n"))
      {
         close(sockfd);
         break;
      }

      // print the receive stuff
      read(sockfd, recv, sizeof(recv));
      fputs(recv, stdout);
      bzero(recv, 1024);

   } while (1);
}

2 个答案:

答案 0 :(得分:1)

在您的服务器代码中,必须在do-while循环中调用accept()函数:

// listening for incoming connection
listen(listen_fd, 10);

do
{ 
    // accept a connection on a socket
    conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);

    ...

    close(conn_fd);
} while(1);

答案 1 :(得分:0)

  

我的问题是,如果我关闭连接,服务器结束的原因   客户。

因为阻塞read调用将返回值0,表示连接已关闭,您会立即忽略该连接。然后尝试(并且失败)将接收到的数据(没有)与字符串进行比较,然后您将尝试将错误消息写入(现已断开连接的)客户端,这将引发SIGPIPE错误,从而终止您的应用。                      - 一些程序员老兄