Главная страница


ru.unix.bsd

 
 - RU.UNIX.BSD ------------------------------------------------------------------
 From : Vadim Goncharov                      2:5020/400     17 Oct 2005  23:49:28
 To : Valentin Davydov
 Subject : Re: discard server
 -------------------------------------------------------------------------------- 
 
 Hi Valentin Davydov! 
 
 On Mon, 17 Oct 2005 15:53:58 +0000 (UTC); Valentin Davydov wrote about 'discard 
 server':
 
  VD> Посоветуйте сабж, пожалуйста. Задача - принимать tcp соединения по некоему
  VD> порту (например, 9), все приходящие данные дропать, в ответ кроме ackов 
  VD> ничего не посылать, по стандартному таймауту штатно закрывать соединения.
  VD> При этом чтобы жрало как можно меньше ресурсов, в идеале - только таблицы
  VD> ядерного tcp/ip стека. Пробовал inetd с его встроенным сервисом, так он 
  VD> нафоркал несколько сотен потомков и скис. Можно, конечно, thttpd взять,
  VD> но нет ли чего попроще, специально для этой цели?
 
 Вот сейчас наваял, жрать должен минимум (естественно, я его проверил
 толко на маленьких нагрзках). Таймауты - только SO_KEEPALIVE, нормальные
 лень было делать.
 
 >=== begin discard.c ===
 
 /* Simple discard server (c) Vadim Goncharov, 2005. 
  * Covered by BSD license, no warranty, etc.
  */
 
 #include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <sys/time.h>
 #include <time.h>
 #include <sys/stat.h>
 #include <strings.h>
 
 #define DISCARDPORTNUM 9
 #define BUFSIZE 4096
 #define BYTE unsigned char
 
 /* Global vars */
 unsigned int listening_port;   /* Port on which we listen for connections */
 int   listening_socket;    /* Socket for incoming connections from clients */
 BYTE  debug;       /* 1 for debug mode, else 0 */
 int   max_sockets;     /* max number of clients we can serve */
 BYTE  quit;        /* 1 if time to break endless loop and quit */
 fd_set mainset;       /* Clients are remebered here */
 BYTE  buf[BUFSIZE];       /* Dummy input buffer data */
 
 void term_signal(int z)
 {
    quit = 1;
 }
 
 void quit_program(void)
 {
    int i;
 
    close(listening_socket);
    
    for (i=0; i < max_sockets; i++)
      if (FD_ISSET(i, &mainset))
        shutdown(i, SHUT_RDWR);
 }
 
 void init_sig(void)
 {  
    struct sigaction sv;  
    
    memset(&sv, 0, sizeof(struct sigaction));
    sv.sa_flags = 0;
    sigemptyset(&sv.sa_mask);
 #ifdef SA_NOCLDWAIT
    sv.sa_flags |= SA_NOCLDWAIT;
 #endif
 #ifdef SA_NOCLDSTOP
    sv.sa_flags |= SA_NOCLDSTOP;
 #endif
    
    sv.sa_handler = SIG_IGN;
    /* Don't want broken pipes to kill the server. */
    sigaction(SIGPIPE, &sv, NULL);
    
    /* ...or any defunct child processes. */
    sigaction(SIGCHLD, &sv, NULL);
    
    if (debug == 0) /* For daemon safety SIGHUP shouldn't kill us. */
      sigaction(SIGHUP, &sv, NULL);
    
    sv.sa_handler = term_signal;
    
    /* Also, shut down properly.  */
    sigaction(SIGTERM, &sv, NULL);
    sigaction(SIGINT, &sv, NULL);
 }
 
 int   sock_nonblock(int sock)
 {
    int flags;  
    
    if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
   return -1;
    }
     
    /* Non blocking mode */
    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
   return -1;
    }
    
    return 0;
 }
 
 int get_listening_socket(int port, int set_to_localhost)
 {
    int sock;
    int yes = 1;
    struct sockaddr_in serv_addr;
    
    if(port == 0)
      return -1;
    
    memset (&serv_addr, 0, sizeof(struct sockaddr_in));
    /* Create socket */
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
   return -1;
    }
    
    /* Fix the address already in use error */
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes,
      sizeof(int)) == -1)
      {
   return -1;
      }
    memset(&serv_addr, 0, sizeof(struct sockaddr_in));
    serv_addr.sin_family = AF_INET;
    if (set_to_localhost) {
      inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
    } else {
      serv_addr.sin_addr.s_addr = INADDR_ANY;
    }
    serv_addr.sin_port = htons(port);
    
    /* Bind socket to port */
    if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
   return -1;
    }
    
    /* Listen on socket */
    if (listen(sock, 100) == -1) {
   return -1;
    }
    
    /* Put socket into non-blocking mode */
    if (sock_nonblock(sock) == -1) {
   return -1;
    }
    
    return(sock);
 }
 
 void  do_read(int fd)
 {
    int n, looping;
    time_t curtime;
 
    looping = 1;
    curtime = time(NULL);  /* read from one client for no more than 1 sec */
    while ((looping) && (time(NULL) <= curtime)) {
      /* function central read */
      n = read(fd, buf, BUFSIZE);
      if (n > 0) {
        continue;
      }
      if (n == -1) { /* an error has occured */
        if (errno == EINTR) {
    if (time(NULL) > curtime) {
      looping = 0;
    }
          continue;
        }
        looping = 0;
        if (errno != EAGAIN) {
    if (debug)
      printf("Error - In do_read()/read() for fd=%d: %s\n", fd, strerror(errno));
        }
      }
      if (n == 0) { /* connection closed */
        if (debug)
          printf("Client with fd=%d closed connection\n", fd);
        looping = 0;
        /* close client and forget about it */
        FD_CLR(fd, &mainset);
        shutdown(fd, SHUT_RDWR);
      }
    }
 }
 
 void get_socket_action(void)
 {
    struct sockaddr_in client;
    int clilen;
    int yes = 1;
    fd_set fds;
    struct timeval tv;
    int i, nfds, maxfd;
    time_t curtime;
 
    tv.tv_sec = 1;
    tv.tv_usec = 0;
 
    FD_ZERO(&fds);
    maxfd = listening_socket;
 
    /* Add our listening tcp socket to the set... */
    if (listening_socket != -1)
      FD_SET(listening_socket, &fds);
 
    /* ... and the established client connections  */
    for (i=0; i < max_sockets; i++)
      if (FD_ISSET(i, &mainset)) {  /* check in loop for setting maxfd */
   FD_SET(i, &fds);
   if (i > maxfd)
     maxfd = i;
      }
    
    /* The very central select, where the program should spend most of its time
 */
    nfds = select(maxfd+1, &fds, NULL, NULL, &tv);
    if (nfds <= 0) {
      if ((nfds < 0) && (errno != EINTR)) {
   if (debug) {
     printf("Error - In get_socket_action()/select(read): %s\n",
 strerror(errno));
   }
      }
      return;
    }
    
    /* Check if it's a new connection */
    if (FD_ISSET(listening_socket, &fds) && (nfds > 0)) {
      nfds--;
      curtime = time(NULL);
      clilen = sizeof(client);
      do {
        i = accept(listening_socket, (struct sockaddr *)&client, &clilen);
        if (i > 0)
    break;
        else
    if ((errno == EAGAIN) || (errno == ECONNABORTED))
      goto check_input;
      } while ((time(NULL) > curtime) && (errno == EINTR));
 
      if (i < 0) {
        if (debug) {
          printf("accept() error: %s\n", strerror(errno));
        }
        goto check_input;
      }
      
      /* Put socket into non-blocking mode */
      if (sock_nonblock(i) == -1) {
   /* can't make socket nonblocking */
   close(i);
   goto check_input;
      }
  
      /* Avoid dead peers */
      if (setsockopt(i, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(int)) == -1) {
   close(i);
   goto check_input;
      }
      
      /* new user accepted */
      FD_SET(i, &mainset);
      if (debug)
        printf("New client connected, fd=%d\n", i);
    }
 
 check_input:
    
    /* Do input from all clients */
    i = 0;
    while ((i < max_sockets) && (nfds > 0)) {
      if (FD_ISSET(i, &fds)) {
        nfds--;
        do_read(i);
      }
      i++;
    }
 }
 
 int main(int argc, char *argv[])
 {
    int fd;
    int erret;
    int x;
    int pid;
    
    /* init vars */
    listening_port = DISCARDPORTNUM;
    max_sockets = getdtablesize();
    if(max_sockets > FD_SETSIZE)
      max_sockets = FD_SETSIZE;
    listening_socket = -1;
    debug = 0;
    quit = 0;
    FD_ZERO(&mainset);
    
    /* prepare server */
    if ((listening_socket = get_listening_socket(listening_port, 0)) == -1)
      {
   printf("Bind failed.\nRemember, to use a listening port below 1024, you need
 to be root.\nAlso, make sure that you don't have another instance of the
 program\nalready running.\n");
   return 1;
      }
    
    if ((argc > 1) && ((strcmp(argv[1], "-d")) == 0))
      debug = 1;
    
    init_sig();
 
    if (debug == 0)
       {
    /* Make program a daemon */
    pid = fork();
    if (pid < 0)
      {
         perror("fork");
         exit(EXIT_FAILURE);
      }
    if (pid > 0)
      exit(EXIT_SUCCESS);
    if (setsid() < 0)
      {
         perror("setsid");
         exit(EXIT_FAILURE);
      }
    pid = fork();
    if (pid > 0)   /* ensure we can't regain control tty */
      exit(EXIT_SUCCESS);
    else if (pid < 0)
      exit(EXIT_FAILURE);;
    
    chdir("/");
    umask(0);
    
            for (x = 0; x <= 2; x++)
      {
         if (close(x) != 0)
    {
              printf("Error - When closing fd=%d while daemonizing, exiting\n",
 x);
              exit(EXIT_FAILURE);
    }
      }
   
    fd = open("/dev/null", O_RDWR);
    if (fd >= 0)
      {
         erret = dup2(fd, 1);
         erret = dup2(fd, 2);
      }
       }
 
    if (debug) {
      printf("Discrad server is up and running in debug mode\n");
    }
    
    /* Main server I/O loop. */
    while (quit == 0)
      {
        get_socket_action();
      }
    quit_program();
    return 0;
 }
 
 >=== end discard.c ===
 
 -- 
 WBR, Vadim Goncharov. ICQ#166852181       mailto:vadim_nuclight@mail.ru
 [Moderator of RU.ANTI-ECOLOGY][FreeBSD][http://antigreen.org][LJ:/nuclight]
 --- slrn/0.9.8.1 on FreeBSD 4.11/i386
  * Origin: Nuclear Lightning @ Tomsk, TPU AVTF Hostel (2:5020/400@fidonet)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 discard server   Valentin Davydov   17 Oct 2005 19:53:58 
 Re: discard server   vladimir.sharun@ukr.net   17 Oct 2005 20:02:35 
 Re: discard server   Alexander Kolesnikoff   18 Oct 2005 04:19:42 
 Re: discard server   Vadim Goncharov   17 Oct 2005 23:49:28 
 Re: discard server   Valentin Davydov   19 Oct 2005 17:41:22 
 Re: discard server   Vadim Goncharov   19 Oct 2005 21:44:40 
 Re: discard server   Anton Yuzhaninov   19 Oct 2005 22:16:57 
 Re: discard server   Vadim Goncharov   19 Oct 2005 22:30:34 
 Re: discard server   Anton Yuzhaninov   19 Oct 2005 23:50:14 
 Re: discard server   Vadim Goncharov   20 Oct 2005 01:39:10 
 discard server   Max Khon   20 Oct 2005 10:39:24 
 Re: discard server   Vadim Goncharov   20 Oct 2005 17:44:24 
 Re: discard server   Alex V. Litovchenko   03 Nov 2005 21:56:54 
 Re: discard server   Andrew Filonov   03 Nov 2005 21:58:27 
 Re: discard server   Igor Sysoev   20 Oct 2005 22:24:42 
 Re: discard server   Vadim Goncharov   21 Oct 2005 02:06:48 
 Re: discard server   Valentin Davydov   21 Oct 2005 15:05:57 
 Re: discard server   Alexander Kolesnikoff   21 Oct 2005 16:48:59 
 Re: discard server   Valentin Davydov   21 Oct 2005 18:14:49 
 Re: discard server   Alexander Kolesnikoff   21 Oct 2005 18:24:40 
 Re: discard server   Valentin Davydov   25 Oct 2005 09:13:42 
 Re: discard server   Vadim Goncharov   22 Oct 2005 03:29:36 
 Re: discard server   Valentin Davydov   25 Oct 2005 09:13:40 
 Re: discard server   Vadim Goncharov   26 Oct 2005 04:22:02 
 Re: discard server   Valentin Davydov   26 Oct 2005 16:09:11 
 Re: discard server   Vadim Goncharov   27 Oct 2005 04:46:47 
 Re: discard server   Vadim Goncharov   22 Oct 2005 04:35:05 
 Re: discard server   Valentin Davydov   20 Oct 2005 10:57:23 
 Re: discard server   Vadim Goncharov   20 Oct 2005 17:48:56 
 Re: discard server   Valentin Davydov   20 Oct 2005 10:57:23 
 Re: discard server   Vadim Goncharov   20 Oct 2005 18:14:01 
 Re: discard server   Alexander Kolesnikoff   18 Oct 2005 04:22:13 
 Re: discard server   Gleb Smirnoff   18 Oct 2005 11:21:18 
 Re: discard server   Vadim Goncharov   18 Oct 2005 19:54:21 
 Re: discard server   Gleb Smirnoff   19 Oct 2005 01:12:18 
 Re: discard server   Valentin Davydov   19 Oct 2005 19:31:53 
 Re: discard server   Anton Yuzhaninov   19 Oct 2005 19:56:05 
Архивное /ru.unix.bsd/10359c2126c7b.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional