The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Перенаправление между 2-мя сокетами. (Дуплекс), !*! asshole, 22-Ноя-08, 14:38  [смотреть все]
Здравствуйте.

Вот какая проблема, на С++. Имеем 2 дискриптора сокета, открытые с 2-мя клиентами или серверами.
Как можно устроить асинхронный обмен данными между ними? Т.е. все данные пришедшие на 1-ый отправлять на 2-ой без изменения и задержки?

Основная проблема в том, что ожидается передача между ними асинхронно, а не пакетами, в любой момент 1-ый может отправить второму что угодно, и наоборот.

  • Перенаправление между 2-мя сокетами. (Дуплекс), !*! Fuzzy, 14:46 , 22-Ноя-08 (1)
    Можно отключить блокировку:

    int tcp_nodelay = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &tcp_nodelay, sizeof(tcp_nodelay));

  • Перенаправление между 2-мя сокетами. (Дуплекс), !*! from_mars, 09:29 , 28-Ноя-08 (6)
    если сделать надо под *никсы, то имхо проще реализовать это с помощью фаервола.
    • Перенаправление между 2-мя сокетами. (Дуплекс), !*! const, 13:19 , 28-Ноя-08 (7)
      >если сделать надо под *никсы, то имхо проще реализовать это с помощью
      >фаервола.

      Смелое решение! :) А что будем делать с сокетами AF_UNIX?

    • Перенаправление между 2-мя сокетами. (Дуплекс), !*! ImPressed, 20:09 , 28-Ноя-08 (8)
      >если сделать надо под *никсы, то имхо проще реализовать это с помощью
      >

      NAT, FireWall и отбражение потров  в  топку.

      Вот реально работающий вариант кода, для перенаправления с одного сокета на другой:

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

             static int forward_port;

             #undef max
             #define max(x,y) ((x) > (y) ? (x) : (y))

             static int
             listen_socket(int listen_port)
             {
                 struct sockaddr_in a;
                 int s;
                 int yes;

                 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                     perror("socket");
                     return -1;
                 }
                 yes = 1;
                 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                         (char *) &yes, sizeof(yes)) < 0) {
                     perror("setsockopt");
                     close(s);
                     return -1;
                 }
                 memset(&a, 0, sizeof(a));
      a.sin_port = htons(listen_port);
                 a.sin_family = AF_INET;
                 if (bind(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
                     perror("bind");
                     close(s);
                     return -1;
                 }
                 printf("accepting connections on port %d\n", listen_port);
                 listen(s, 10);
                 return s;
             }

             static int
             connect_socket(int connect_port, char *address)
             {
                 struct sockaddr_in a;
                 int s;

                 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                     perror("socket");
                     close(s);
                     return -1;
                 }

                 memset(&a, 0, sizeof(a));
                 a.sin_port = htons(connect_port);
                 a.sin_family = AF_INET;

                 if (!inet_aton(address, (struct in_addr *) &a.sin_addr.s_addr)) {
                     perror("bad IP address format");
                     close(s);
                     return -1;
                 }

                 if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
                     perror("connect()");
                     shutdown(s, SHUT_RDWR);
                     close(s);
                     return -1;
                 }
                 return s;
             }
      #define SHUT_FD1 {                      \
                     if (fd1 >= 0) {                 \
                         shutdown(fd1, SHUT_RDWR);   \
                         close(fd1);                 \
                         fd1 = -1;                   \
                     }                               \
                 }

             #define SHUT_FD2 {                      \
                     if (fd2 >= 0) {                 \
                         shutdown(fd2, SHUT_RDWR);   \
                         close(fd2);                 \
                         fd2 = -1;                   \
                     }                               \
                 }

             #define BUF_SIZE 1024

             int
             main(int argc, char **argv)
             {
                 int h;
                 int fd1 = -1, fd2 = -1;
                 char buf1[BUF_SIZE], buf2[BUF_SIZE];
                 int buf1_avail, buf1_written;
                 int buf2_avail, buf2_written;

                 if (argc != 4) {
                     fprintf(stderr,
                              "Usage\n\tfwd <listen-port> "
                              "<forward-to-port> <forward-to-ip-address>\n");
                     exit(EXIT_FAILURE);
                 }

                 signal(SIGPIPE, SIG_IGN);

                 forward_port = atoi(argv[2]);

                 h = listen_socket(atoi(argv[1]));
                 if (h < 0)
                     exit(EXIT_FAILURE);
      for (;;) {
                     int r, nfds = 0;
                     fd_set rd, wr, er;
                     FD_ZERO(&rd);
                     FD_ZERO(&wr);
                     FD_ZERO(&er);
                     FD_SET(h, &rd);
                     nfds = max(nfds, h);
                     if (fd1 > 0 && buf1_avail < BUF_SIZE) {
                         FD_SET(fd1, &rd);
                         nfds = max(nfds, fd1);
                     }
                     if (fd2 > 0 && buf2_avail < BUF_SIZE) {
                         FD_SET(fd2, &rd);
                         nfds = max(nfds, fd2);
                     }
                     if (fd1 > 0
                         && buf2_avail - buf2_written > 0) {
                         FD_SET(fd1, &wr);
                         nfds = max(nfds, fd1);
                     }
                     if (fd2 > 0
                         && buf1_avail - buf1_written > 0) {
                         FD_SET(fd2, &wr);
                         nfds = max(nfds, fd2);
                     }
                     if (fd1 > 0) {
                         FD_SET(fd1, &er);
                         nfds = max(nfds, fd1);
                     }
                     if (fd2 > 0) {
                         FD_SET(fd2, &er);
                         nfds = max(nfds, fd2);
                     }

                     r = select(nfds + 1, &rd, &wr, &er, NULL);

                     if (r == -1 && errno == EINTR)
                         continue;
                     if (r < 0) {
                         perror("select()");
                         exit(EXIT_FAILURE);
                     }
      if (FD_ISSET(h, &rd)) {
                         unsigned int l;
                         struct sockaddr_in client_address;
                         memset(&client_address, 0, l = sizeof(client_address));
                         r = accept(h, (struct sockaddr *) &client_address, &l);
                         if (r < 0) {
                             perror("accept()");
                         } else {
                             SHUT_FD1;
                             SHUT_FD2;
                             buf1_avail = buf1_written = 0;
                             buf2_avail = buf2_written = 0;
                             fd1 = r;
                             fd2 =
                                 connect_socket(forward_port, argv[3]);
                             if (fd2 < 0) {
                                 SHUT_FD1;
                             } else
                                 printf("connect from %s\n",
                                         inet_ntoa(client_address.sin_addr));
                         }
                     }
      /* NB: read oob data before normal reads */
                     if (fd1 > 0)
                         if (FD_ISSET(fd1, &er)) {
                             char c;
                             errno = 0;
                             r = recv(fd1, &c, 1, MSG_OOB);
                             if (r < 1) {
                                 SHUT_FD1;
                             } else
                                 send(fd2, &c, 1, MSG_OOB);
                         }
                     if (fd2 > 0)
                         if (FD_ISSET(fd2, &er)) {
                             char c;
                             errno = 0;
                             r = recv(fd2, &c, 1, MSG_OOB);
                             if (r < 1) {
                                 SHUT_FD1;
                             } else
                                 send(fd1, &c, 1, MSG_OOB);
                         }
                     if (fd1 > 0)
                         if (FD_ISSET(fd1, &rd)) {
                             r =
                                 read(fd1, buf1 + buf1_avail,
                                       BUF_SIZE - buf1_avail);
                             if (r < 1) {
                                 SHUT_FD1;
                             } else
                                 buf1_avail += r;
                         }
                     if (fd2 > 0)
                         if (FD_ISSET(fd2, &rd)) {
                             r =
                                 read(fd2, buf2 + buf2_avail,
                                       BUF_SIZE - buf2_avail);
                             if (r < 1) {
                                 SHUT_FD2;
                             } else
                                 buf2_avail += r;
                         }
      if (fd1 > 0)
                         if (FD_ISSET(fd1, &wr)) {
                             r =
                                 write(fd1, buf2 + buf2_written,
                                        buf2_avail - buf2_written);
                             if (r < 1) {
                                 SHUT_FD1;
                             } else
                                 buf2_written += r;
                         }
                     if (fd2 > 0)
                         if (FD_ISSET(fd2, &wr)) {
                             r =
                                 write(fd2, buf1 + buf1_written,
                                        buf1_avail - buf1_written);
                             if (r < 1) {
                                 SHUT_FD2;
                             } else
                                 buf1_written += r;
                         }
             /* check if write data has caught read data */
                     if (buf1_written == buf1_avail)
                         buf1_written = buf1_avail = 0;
                     if (buf2_written == buf2_avail)
                         buf2_written = buf2_avail = 0;
             /* one side has closed the connection, keep
                writing to the other side until empty */
                     if (fd1 < 0 && buf1_avail - buf1_written == 0) {
                         SHUT_FD2;
                     }
                     if (fd2 < 0 && buf2_avail - buf2_written == 0) {
                         SHUT_FD1;
                     }
                 }
                 exit(EXIT_SUCCESS);
             }

      Пользуйтесь ради бога если надо, и мой вам совет -- по чаще заглядывайте в MAN-страницы, там много полезного есть.
      PS:
         Этот код взят из man 2 select_tut
         Советую вам повнимательнее читать маны.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру