Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677

Утечки при использовании порта завершения и соккетов

29.10.2015, 14:33. Показов 1149. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, уважаемые Гуру! Реализовываю сервер с использованием порта завершения. Всё работает, всё прекрасно. Одно меня смущает - невозможно удалить хэндл из порта, пока не произойдёт завершение считывания-записи. Т.е. если клиент просто отключается, то порт продолжит хранить данные об этом хендле. По крайней мере я так понял из сети. Есть 2 идеи. 1 - фиктивные сообщения по таймауту с типом операции "удалить", 2 - идея двойной буфферизации. Т.е. имеем 2 порта завершения, в один момент активен только один из них. Как только количество хендлов превышает некоторый предел, порты переключаются. Это я основываю на предположении, что CloseHandle сама очистит устаревшие элементы. Собственно вопрос - что посоветуете? Читал много разного, но не нашёл конкретного решения по утечкам. А в остальном должен признать, что порт завершения - реально крутая вещи ИМХО.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.10.2015, 14:33
Ответы с готовыми решениями:

Утечки памяти при использовании ExpandableListView
Всем здравствуйте. Сразу оговорюсь, что проект выполняется на Xamarin.Android. Но т.к. сама платформа не должна существенно отличаться от...

Утечки памяти при использовании new/delete для двумерных массивов
Добрый день. Суть в том, что есть несколько функций, получающих на вход и возвращающих двумерные массивы. Реализация передачи массивов...

Определение и принцип работы порта завершения ввода и вывода
Что такое порт завершения ввода и вывода данных и как он работает ? Это просто пул прерываемых сокетов?

12
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 14:53
Цитата Сообщение от Retyrn0 Посмотреть сообщение
Одно меня смущает - невозможно удалить хэндл из порта, пока не произойдёт завершение считывания-записи. Т.е. если клиент просто отключается, то порт продолжит хранить данные об этом хендле.
Нет, не так. Клиент отключается - операция на сокете завершается - в
порт приходит сообщение. Далее его может обработать один из потоков пула.

Цитата Сообщение от Retyrn0 Посмотреть сообщение
Собственно вопрос - что посоветуете? Читал много разного, но не нашёл конкретного решения по утечкам
Нет там утечек. Когда вы заканчиваете работать с соединением, то хэндл
сокета должен быть закрыт. Начиная с этого момента порт больше не
использует данный хэндл. Все.

Цитата Сообщение от Retyrn0 Посмотреть сообщение
А в остальном должен признать, что порт завершения - реально крутая вещи
Это да. Хотя написать качественный сервер на портах завершения - задача не из простых.
1
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 15:46  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Нет там утечек. Когда вы заканчиваете работать с соединением, то хэндл
сокета должен быть закрыт. Начиная с этого момента порт больше не
использует данный хэндл. Все.
Звучит обнадёживающе, но мой сервер при событии отключения выводит сколько активных соединений. Я открываю, скажем, 5 вкладок. Потом все закрываю. Потом открываю новую - сервер выдаёт, что у меня 6 активных подключений. Если Вы имеете ввиду, что из порта удаляется сам хендл закрывшегося соккета, то есть возможность это обработать? Я ведь выделяю под каждый память для "данных завершения". Если утечек в порте не будет, то утечки будут в моей программе. Каким образом освобождать ресурсы?

Добавлено через 2 минуты
Простите, не прочитал...
Цитата Сообщение от Убежденный Посмотреть сообщение
Клиент отключается - операция на сокете завершается - в
порт приходит сообщение.
Т.е. если я навесил ожидание завершения считывания, то просто в обработчике определить закрыт ли соккет и если закрыт, освободить ресурсы? Правильно я понял?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 15:47
Я вижу здесь две совершенно разные проблемы:

1. отключение клиента (возможно, аварийное).

2. отсоединение сокетного хэндла от порта завершения.

Какую вы пытаетесь решить ?
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 15:53  [ТС]
И могу ли я быть уверен, что операция завершения произойдёт всегда?

Добавлено через 1 минуту
Цитата Сообщение от Убежденный Посмотреть сообщение
Какую вы пытаетесь решить ?
Обе. Сервер будет работать постоянно и если при одном из двух вариантов произойдёт даже малейшая утечка, то со временем может получиться очень не приятно.

Добавлено через 3 минуты
Веб-соккетные подключения - необходимо KEEPALIVED - нужно всё держать. Но важно, чтобы при любом варианте отключения клиента сервер освобождал ресурсы. Текущая задача - 1 из Ваших предположенных -
Цитата Сообщение от Убежденный Посмотреть сообщение
1. отключение клиента (возможно, аварийное).
Добавлено через 1 минуту
Есть конечно вариант вытесняющего пула памяти для данных завершения, но если есть возможность решить вопрос иначе...
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 15:55
1. Клиент-сервер, соединение установлено по TCP. Если одна из сторон закрывает
соединение, другая сторона при попытке чтения или записи получает соответствующий
код ошибки (0 для graceful shutdown, -1 в остальных случаях). Если хэндл сокета
ассоциирован с портом завершения, порт выдает сигнал завершения и его сможет
обработать любой свободный поток из пула.

Если связь между клиентом и сервером была разорвана (например, упала сеть),
то такой сигнал может и не прийти, или прийти, но с большой задержкой.
Здесь возможет вариант с установкой опции keepalive для сокета.
Я несколько раз писал такие серверы на I/O completion ports, мне эта
опция keepalive ни разу не была полезной. Это так, к слову.

2. Когда хэндл, связанный с портом завершения, закрывается (CloseHandle, например),
ассоциация между ним и портом завершения тоже разрывается, а все внутренние
ресурсы, на которые указывал хэндл, очищаются.

Цитата Сообщение от Retyrn0 Посмотреть сообщение
мой сервер при событии отключения выводит сколько активных соединений. Я открываю, скажем, 5 вкладок. Потом все закрываю. Потом открываю новую - сервер выдаёт, что у меня 6 активных подключений.
Это проблема сервера, а не портов завершения или сокетов.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 16:00  [ТС]
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
//---------------------------------------------------------------------------------------------------
//Функция потока сервера для обслуживания порта завершения
//---------------------------------------------------------------------------------------------------
DWORD WINAPI ServerPool(HANDLE hp)
{
    unsigned long bytes;     // Кол-во байтов
    unsigned long key;       // Значение, асоциированное с хендлом порта
    char buffer[128];        // Буфер для сообщений
    LPOVERLAPPED overlapped; // Структура асинхронного I/O
    HANDLE hport=hp;         // Дескриптор порта
    DWORD flags;             // Флаги ф-ции WSARecv()
    while(serverrun) 
    {
        // Получаем информацию о завершении операции
        if(GetQueuedCompletionStatus(hport, &bytes, &key, &overlapped, INFINITE)) 
        {
            printf("-----------------------New operation-----------------------\n");
            // Операция завершена успешно
            Sock*op=(Sock*)overlapped;
            // Определяем тип завершенной операции и выполняем соответствующие действия
            switch(op->type) 
            {
                //Завершена отправка данных
            case Sock::op_type_send:
                delete[]op->buff;
                delete op;
                break;
                //Завершен приём данных
            case Sock::op_type_recv:
                if(!bytes) 
                {
                    //Соединение с данным клиентом закрыто
                    ClientList.remove(op->sock);
                    closesocket(op->sock);
                    strcpy(buffer,"Client %d disconnected, active clients %d\n");
                    printf(buffer,op->numb,ClientList.size());
                    break;
                }
                op->buff[bytes]='\0';
                strcpy(buffer,"From client %d recv message %s\n");
                printf(buffer,op->numb,op->buff);
                Recv(op);
                unsigned long b;
                WSABUF buf;
                buf.buf = op->buff;
                buf.len = BUFF_SIZE;   // buffer_len – постоянная величина 
                if(!WSARecv(op->sock,&buf,1,&b,&flags,op,0))
                {
                    strcpy(buffer,"Error: WSARecv");
                    printf("%s %d\n",buffer, WSAGetLastError());
                }
            }
        }
        else 
        {
            if(!overlapped)
            {
                // Ошибка с портом
                // Закрываем все сокеты, закрываем порт, очищаем список
                for(list<SOCKET>::iterator i=ClientList.begin();i!=ClientList.end();i++)
                {
                    closesocket(*i);
                }
                ClientList.clear();
                closesocket(server_sock);
                CloseHandle(hport);
                strcpy(buffer,"Error: complition port %d, server is stoped\n");
                printf(buffer,GetLastError());
                _getch();
                exit(0);
            }
            else 
            {
                //Закрываем соединение с клиентом
                closesocket(((Sock*)overlapped)->sock);
                ClientList.remove(((Sock*)overlapped)->sock);
                strcpy(buffer,"Client %d disconnected, active clients %d\n");
                printf(buffer,((Sock*)overlapped)->numb,ClientList.size());
            }
        }
    }
    return 0;
}
Добавлено через 2 минуты
Только что в строку 17 добавил вывод на экран текста, чтобы понимать, что возникло завершение чего-либо. При закрытии вкладки сообщение не выводится - порт завершения не запускает пул почему-то. Закрытие вкладки в браузере - наверное не аварийная ситуация? И всё же что-то не работает обработчик. Подскажите пожалуйста, уже мозг кипит. Вроде всё правильно, а не работает.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 16:20
Вставьте printf сразу после вызова (не важно, успешного или нет) GetQueuedCompletionStatus.
И еще мне по коду непонятно, зачем здесь вызывается break: ведь после закрытия соединения
рабочие потоки должны продолжать работу...
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 16:44  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Вставьте printf сразу после вызова (не важно, успешного или нет) GetQueuedCompletionStatus.
Как раз так и поступил - в 17 строке стоит принтф. При закрытии вкладки не выводится.
Цитата Сообщение от Убежденный Посмотреть сообщение
И еще мне по коду непонятно, зачем здесь вызывается break: ведь после закрытия соединения
рабочие потоки должны продолжать работу...
Там break стоят для выхода из switch, а не из цикла. Если бы проблема была в этом, то у меня запускается 2 потока на машине и в случае выхода из цикла больше чем 2 раза вкладку открыть не удалось бы.

Добавлено через 1 минуту
Сейчас ещё попробую вставить на не успешный вызов.

Добавлено через 4 минуты
Не помогло. Добавила в конец цикла вывод текста - ничего не пишет при закрытии вкладки.

Добавлено через 2 минуты
А должно выводиться каждый раз при вообще любом событии завершения. Чтение-запись - работает как надо и всё прекрасно, но закрытие вкладки браузера не вызывает события завершения чтения, хотя я так понял должно?
Цитата Сообщение от Убежденный Посмотреть сообщение
Если хэндл сокета
ассоциирован с портом завершения, порт выдает сигнал завершения и его сможет
обработать любой свободный поток из пула.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 16:59
Цитата Сообщение от Retyrn0 Посмотреть сообщение
но закрытие вкладки браузера не вызывает события завершения чтения, хотя я так понял должно?
Попробуй тестировать без всех этих браузеров, вкладок и т.п.
Просто через "голые" сокеты обращаться к серверу, писать-читать, а
затем делать shutdown/closesocket.
0
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 17:03  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Попробуй тестировать без всех этих браузеров, вкладок и т.п.
Просто через "голые" сокеты обращаться к серверу, писать-читать, а
затем делать shutdown/closesocket.
Тоже подумал что стоит грешить на браузер...попробую, но проблема в том, что сервер должен работать именно с браузером. Т.е. даже если мимо браузера всё заработает, то проблема сама собой не решится =(
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.10.2015, 17:06
Да я понимаю. Но все-таки начинать нужно с главного: голый клиент + голый сервер.
И отлаживаться сперва на такой схеме, а уже потом подключать сложности в виде
браузеров, прокси, разрывов сети и т.п.
1
45 / 48 / 5
Регистрация: 24.06.2013
Сообщений: 677
29.10.2015, 17:10  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Да я понимаю. Но все-таки начинать нужно с главного: голый клиент + голый сервер.
И отлаживаться сперва на такой схеме, а уже потом подключать сложности в виде
браузеров, прокси, разрывов сети и т.п.
Тоже верно. Спасибо, буду вертеть. Когда доделаю, выложу, может кому в будущем пригодится.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.10.2015, 17:10
Помогаю со студенческими работами здесь

Чтение из COM порта, При чтении из порта зависает read()
Каждому рано или поздно приходится программировать com порт. Вот и мой черед пришол. Я ужу умею: Откривать,закривать, писать. а читать не...

Утечки при работе с динамической памятью
Здравствуйте, отправляю задачу на сервер, пишут:&quot;Утечки памяти&quot;. Для входных данных: 3 Вот код: #include &lt;stdio.h&gt; #include...

Битовые утечки при записи данных на диск
Доброго дня форумчане! Сорри если оффтоп но... Пишу в консольке на C++ (MSVCE 2010) различные движки по расчетам и тут столкнулся с...

ClientDataSet, Blob утечки памяти при записи в файл
столкнулся с такой ситуацией, есть ClientdataSet в котором есть блоб поле, которое я записываю процедурой ниже: Procedure...

Избежать утечки памяти при преобразовании строки в массив символов
Всем привет! Как избежать утечки памяти в таком коде: char* ConvertString(String input) { char *output = new char; ...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru