Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/25: Рейтинг темы: голосов - 25, средняя оценка - 4.68
Liath

Несколько сокетов в одном приложении

10.02.2011, 22:05. Показов 5266. Ответов 23
Метки нет (Все метки)

Доброе время суток!
Нужна помощь, нужно сделать прогу которая сразу работает с 2-мя сокетами.

Задача: слушать 1-ый сокет и передавать передавать все начинающееся с !текст на 2 сокет. (что-то типа ретранслятора)

Вопрос как организовать 2 сокета 1 как бы сервер второй как клиен все в 1 файле подскажите а то не выходит.... По 1 сделать могу, а скрестить не выходит....
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.02.2011, 22:05
Ответы с готовыми решениями:

Несколько сокетов в одном приложении
Знакомый говорил, что если приложение будет держать несколько сокетов, то это может вызвать проблемы. Так ли это?

Несколько форм в одном приложении
Проблема состоит в следующем: Приложение состоит из формы, при нажатии на кнопку должно открыться окно для ввода нескольких данных и...

Несколько Proxy в одном приложении
Здравствуйте! Помогите, пожалуйста, с одной проблемой. Недавно на сервере Mail.Ru Агента в целях борьбы со спамерами сделали жёсткое,...

23
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
16.02.2011, 03:10
recv без блокировки
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <netinet/in.h>
#include <linux/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
 
int main(void)
{
    struct sockaddr_in data;
    int sockd, nsd;
    char buf[100];
    int n, count;
    
    sockd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    data.sin_family = AF_INET;
    data.sin_port = htons(1030);
    data.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    bind(sockd, (const void *) &data, sizeof data);
 
    while (listen(sockd, 5) == 0) {
        printf("listen...\n");
        if ((nsd = accept(sockd, NULL, NULL)) >= 0) {
            for (count = 0; count < 3; ) {
                putchar('x');
                if ((n = recv(nsd, buf, 100, MSG_DONTWAIT)) > 0) {
                    printf("I get\n");
                    printf("data: .%.*s.\n", n, buf);
                    printf("size: %d\n", n);
                    count++;
                }
            }
            close(nsd);
        }
    }
    
    close(sockd);
    return 0;    
}

Цитата Сообщение от g_u_e_s_t
В смысле Вам показать пример к man select
да, применительно к этой задаче,
о которой речь
Задача: слушать 1-ый сокет и передавать передавать все начинающееся с !текст на 2 сокет. (что-то типа ретранслятора)

Цитата Сообщение от g_u_e_s_t
Может проще ставить O_NONBLOCK и любой мультиплексор?
мультиплескор - это что ? select чтоли, poll и так далее ?
а копировать сюда man select не надо
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
16.02.2011, 09:04
C
1
2
3
4
5
6
7
8
9
10
11
12
        if ((nsd = accept(sockd, NULL, NULL)) >= 0) {
            for (count = 0; count < 3; ) {
                putchar('x');
                if ((n = recv(nsd, buf, 100, MSG_DONTWAIT)) > 0) {
                    printf("I get\n");
                    printf("data: .%.*s.\n", n, buf);
                    printf("size: %d\n", n);
                    count++;
                }
            }
            close(nsd);
        }
с MSG_DONTWAIT код стал только хуже. recv() получает EAGAIN и цикл повторяется в холостую.

да, применительно к этой задаче,
мультиплескор - это что ? select чтоли, poll и так далее ?
а копировать сюда man select не надо
Да, именно они.
Извините, но писать что-то специально сюда нет желания. Вот вам кусочек кода 8ми летней давности, до того как его переписали на eventlib. На триды и socketpair() можно не обращать внимания т.к. в задаче этого топика они не нужны. Для listenfd установлен O_NONBLOCK

server_loop()
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
void
server_loop(int listenfd)
{
    fd_set rset, wset;
    size_t stack;
    int flags, i, n, nr, sp[2];
 
    /* Creates an socket pair for notify communications. */
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp))
        return;
    if ((flags = fcntl(sp[0], F_GETFL, 0)) == -1 ||
        fcntl(sp[0], F_SETFL, flags | O_NONBLOCK) == -1 ||
        (flags = fcntl(sp[1], F_GETFL, 0)) == -1 ||
        fcntl(sp[1], F_SETFL, flags | O_NONBLOCK) == -1)
        return;
 
    /* Setup server. */
    memset(&server, 0, sizeof(server));
    if ((server.buf = calloc(max_threads, sizeof(char))) == NULL)
        return;
    server.fd = listenfd;
    server.nfd = sp[0];
    server.cfd = sp[1];
    server.free_slots = max_sessions;
    if ((errno = pthread_attr_init(&server.attr)))
        return;
#ifdef DEBUG
    if (pthread_attr_getstacksize(&server.attr, &stack) == 0)
        logmsg(LOG_DEBUG, "%s(): default stack size is %d byte(s)",
            __FUNCTION__, stack);
#endif
    stack = PTHREAD_STACK_MIN + STACK_SIZE;
    pthread_attr_setstacksize(&server.attr, stack);
#ifdef DEBUG
    logmsg(LOG_DEBUG, "%s(): new stack size is %d byte(s)",
        __FUNCTION__, stack);
#endif
    pthread_attr_setdetachstate(&server.attr, PTHREAD_CREATE_JOINABLE);
    TAILQ_INIT(&server.queue);
    FD_SET(server.fd, &server.rset);
    FD_SET(server.nfd, &server.rset);
 
    for (;;) {
        if (server.got_term == 1) {
            server_exit();
            return;
        }
 
        server_init();
        rset = server.rset;
        wset = server.wset;
 
        n = select(server.max_fd + 1, &rset, &wset, NULL,
            server.use_timeout ? &server.timeout : NULL);
#ifdef DEBUG
        logmsg(LOG_DEBUG, "%s(%d,%d): %d",
            __FUNCTION__, server.max_fd + 1, server.use_timeout, n);
#endif
        if (n == -1) {
            if (errno == EINTR) {
                if (server.got_term == 0)
                    continue;
                server_exit();
                return;
            }
            logmsg(LOG_ERR, "select(): %s",
                errno ? strerror(errno) : "error.");
            return;
        }
 
        if (n == 0)
            continue;
 
        /* Accept all incoming connections if any.*/
        if (FD_ISSET(server.fd, &rset)) {
            server_accept();
            if (--n == 0)
                continue;
        }
 
        /* Loop on clients array */
        for (i = 0; i <= server.max_index; i++) {
            if (clients[i] == NULL)
                continue;
 
            /* Read. */
            if (FD_ISSET(clients[i]->fd, &rset)) {
                server_read(i);
                if (--n == 0)
                    break;
                else
                    continue;
            }
 
            /* Write. */
            if (FD_ISSET(clients[i]->fd, &wset)) {
                server_write(i);
                if (--n == 0)
                    break;
                else
                    continue;
            }
        }
        if (n == 0)
            continue;
 
        /* Check notify socket. */
        if (FD_ISSET(server.nfd, &rset)) {
            n--;
            while ((nr = read(server.nfd, server.buf,
                sizeof(server.buf))) != 1);
            if (nr == -1)
                logmsg(LOG_ERR, "error on notify sockect: %s",
                    strerror(errno));
        }
 
        /* Not possible but... */
        if (n > 0) {
            logmsg(LOG_ERR, "Shit is happens.");
            server_exit();
            return;
        }
    }
}
1
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
16.02.2011, 09:45
C
1
2
3
4
5
6
7
8
9
                /* Check notify socket. */
                if (FD_ISSET(server.nfd, &rset)) {
                        n--;
                        while ((nr = read(server.nfd, server.buf,
                            sizeof(server.buf))) != 1);
                        if (nr == -1)
                                logmsg(LOG_ERR, "error on notify sockect: %s",
                                    strerror(errno));
                }
это что ?

для русских написано чтоли ?
C
1
logmsg(LOG_ERR, "Shit is happens.");


Цитата Сообщение от g_u_e_s_t
recv() получает EAGAIN и цикл повторяется в холостую.
и что, это проверить нельзя ?
просто ты утверждал, что на блокированном сокете recv() будет спать

Цитата Сообщение от g_u_e_s_t
Извините, но писать что-то специально сюда нет желания.
конечно, может же не получиться

C
1
sizeof(char)
всегда равен еденице
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
16.02.2011, 10:18
Цитата Сообщение от accept Посмотреть сообщение
C
1
2
3
4
5
6
7
8
9
                /* Check notify socket. */
                if (FD_ISSET(server.nfd, &rset)) {
                        n--;
                        while ((nr = read(server.nfd, server.buf,
                            sizeof(server.buf))) != 1);
                        if (nr == -1)
                                logmsg(LOG_ERR, "error on notify sockect: %s",
                                    strerror(errno));
                }
это что ?
Это чтение одно-байтовых сообщений от тридов из socketpair() на котороe я просил не обращать внимание. По чему по байту? По тому что на sunos5 не удалось за дешево обработать SA_RESTART в тридах из которых сюда прилетают сообщения.

для русских написано чтоли ?
C
1
logmsg(LOG_ERR, "Shit is happens.");
Если честно, я не интересовался национальностью заказчиков...


и что, это проверить нельзя ?
просто ты утверждал, что на блокированном сокете recv() будет спать
Так ведь и спит. MSG_DONTWAIT это и есть _полный_ аналог O_NONBLOCK для отдельного сискола.
Проверить можно и нужно. Но от проверки на EAGAIN в вашем коде ровном счетом ничего не измениться. Вот если добавить проверку на 0, то покрайне мере уйдет вечный цикл. Но я то пытаюсь донести до вас, что если перед собственно попыткой чтения проверять готовность сокета к чтению то будет гораздо лучше и в итоге программа сможет обслуживать больше одного клиента без всяких потоков.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.02.2011, 10:18

Несколько прокси в одном приложении
Всех приветствую! Недавно я начал изучать Си++, вот пишу мою программу... Проблема в следующем... В программе задаются 10 прокси из...

Несколько форм OpenGL в одном приложении
Всем доброго времени суток)) Столкнулся с такой проблемой, в приложении несколько форм OpenGL... Дописав первую форму, перешел к работе со...

Несколько подходов к работе с БД в одном приложении
Есть веб сайт ASP.net в нем импользуется несколько БД. Допустимо ли использовать разные подходы к работе с БД. например с одной базой...

А можно ли в одном приложении иметь в главном окне несколько дочерних с OpenGL?
А можно ли в одном приложении иметь в главном окне несколько дочерних с OpenGL? Добавлено через 43 минуты И как это сделать?

Несколько сущностей в одном веб-приложении и каждого свой кабинет.(Аутентификация и авторизация; java, jdbc)
Добрый день, Уважаемые коллеги. Пишу веб-приложение на java используя servlet API + JSP, DB MySQL + JDBC, Bootstrap и так далее. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
24
Ответ Создать тему
Новые блоги и статьи
23. что сделано за последнее время.
anaschu 17.06.2026
• Эталон: Клиника НИИ питания РАМН, Москва — централизованный пищеблок, 225 коек, 180 пациентов • Git: репозиторий med2, ветка абсентеизм. Рабочий файл: СРесурсами1_v4. alp • Смежный проект:. . .
22. Подключение слоя системной динамики (потоковые диффуры): экономические метрики модели
anaschu 17.06.2026
Апдейт модели: финансовый контур, разделение затрат Продолжаю развивать модель рабочего коллектива на AnyLogic. В этот раз работа шла над агентом Экономика — финансовым SD-слоем модели. Задача:. . .
[golang] Insert Delete GetRandom O(1) (Leetcode: 380)
alhaos 16.06.2026
Insert Delete GetRandom O(1) Сложность: Medium Источник: LeetCode 380 Задача Реализовать структуру данных RandomizedSet, которая поддерживает следующие операции за O(1) в среднем:
Свет в конце тоннеля
kumehtar 16.06.2026
Поймал себя на одной мысли. Раньше мне всегда казалось неправильным жить без чёткого понимания, куда всё идёт. Будто я иду по дороге судьбы, но не знаю, куда она ведёт. А раз не знаю — значит,. . .
[golang] Реализация стека с поддержкой получения минимального элемента за O(1)
alhaos 16.06.2026
Min Stack Сложность: Medium Источник: LeetCode 155 Задача: Реализовать стек который поддерживает push, pop, top и получение минимального элемента за O(1). Методы:
[golang] Конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов.
alhaos 10.06.2026
Задача Реализовать конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов. Сигнатура func Fetch(urls string, maxConcurrent int) Result Пример urls :=. . .
[golang] Состояние гонки (race condition)
alhaos 10.06.2026
Состояние гонки (race condition) Состояние гонки (Race Condition) — это ошибка, возникающая при одновременном доступе нескольких горутин к одним и тем же данным без должной синхронизации. При этом. . .
Взрослые отношения, и почему они не получаются
kumehtar 09.06.2026
Когда в детстве ребёнок не получает от родителей чего-то важного, он лишается не просто приятных переживаний, а основы для формирования определённых внутренних качеств и навыков. Если ребёнок не. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru