Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Особенности работы с IOCP


Автор: NickAnd 27.3.2010, 16:23
Пишу сервер с использованием IOCP.
1. Правильно ли для каждого вызова WSARecv, WSASend использовать свою структуру WSAOverlapped?
2. Как узнать, когда можно освободить память отведенную под WSAOverlapped?


Автор: Демо 27.3.2010, 16:38
Цитата(NickAnd @  27.3.2010,  16:23 Найти цитируемый пост)
1. Правильно ли для каждого вызова WSARecv, WSASend использовать свою структуру WSAOverlapped?


Не то чтобы неправильно, но не стоит каждый раз создавать.
Созданной один раз структуры хватит на всё время работы с созданным сокетом.


Цитата(NickAnd @  27.3.2010,  16:23 Найти цитируемый пост)
2. Как узнать, когда можно освободить память отведенную под WSAOverlapped?


Когда закончишь работать с перекрытым в/в с сокетом.

т.е. после CloseSocket можно освобождать память.

Автор: NickAnd 27.3.2010, 17:08
У меня задача чуть сложнее:
Сервер принимает данные от клиента (WSARecv), передает на обработку и снова принимает (WSARecv). Для этой цепочки используется одна ("постоянная") WSAOverlapped.

В то же время асинхронно (по факту обработки) могут возникать данные для передачи обратно клиенту  (WSASend). Такие вызовы WSASend я делаю с отдельной ("временной") структурой WSAOverlpaped (отдельная под каждый вызов).

Соответственно как только получаю подтверждение завершения такой операции (GetQueuedCompletionStatus), то освобождаю память выделенную под "временную" WSAOverlapped (она мне больше не нужна).

Но, проблема в том, что FastMM4 иногда ругается: "изменились данные в ранее освобожденном блоке" и четко указывает мне на блок, который ранее выделялся для WSAOverlapped и конечно же был освобожден. Т.е. это  run-time ошибка FastMM4.

Есть подозрение, что Windows изменяет содержимое WSAOverlapped после успешного завершенния операции ввода-вывода.

Что посоветуете?



Автор: Демо 27.3.2010, 18:11
Цитата(NickAnd @  27.3.2010,  17:08 Найти цитируемый пост)
Есть подозрение, что Windows изменяет содержимое WSAOverlapped после успешного завершенния операции ввода-вывода.


Я думаю, что можно быть полностью уверенным в этом, так как структура регистрируется при вызове WSARecv.

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

Результат использования логичен - AV.

Добавлено через 1 минуту и 4 секунды
Цитата(NickAnd @  27.3.2010,  17:08 Найти цитируемый пост)
Что посоветуете?


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

Добавлено через 3 минуты и 54 секунды
Хотя насчёт одной структуры могу быть неправ.

Добавлено через 4 минуты и 35 секунд
Есть возможность код выложить?

Добавлено через 11 минут и 7 секунд
А Event в каждой структуре создаёшь?

Автор: NickAnd 27.3.2010, 18:48
Цитата(Демо @ 27.3.2010,  18:11)
Возникает вопрос - зачем используется разные структуры для одного и того же сокета.

Логично. Но мне не совсем понятна роль структуры.
В связи с этим вопрос: нужно ли ее обнулять перед каждым вызовом WSARecv, WSASend

Добавлено через 8 минут и 18 секунд
Цитата(Демо @ 27.3.2010,  18:11)
В любом случае передача данных выполняется последовательно.

Не очень согласен.
Возможна ситуация, когда сервер ждет от клиента данные (завершения очередного WSARecv) а в это время уже отправил несколько раз данные (WSASend) для клиента.

И еще, после закрытия сокета со стороны клиента не могу нормально освободить память даже для "одной на сокет" WSAOverlapped-структуры.
Причина -- все та же: изменение данных структуры системой после завершения операции ввода-вывода.

Может есть все-таки "грамотный" способ определения того момента, когда она уже не используется и может быть освобождена?

Автор: Демо 27.3.2010, 19:15
Вот из MSD полезный материал - http://msdn.microsoft.com/en-us/library/ms686358(VS.85).aspx
Вроде как Event в твоём случае обязательно должен использоваться для каждой структуры.

Цитата(NickAnd @  27.3.2010,  18:48 Найти цитируемый пост)
В связи с этим вопрос: нужно ли ее обнулять перед каждым вызовом WSARecv, WSASend


Да, перед каждой операцией.

Добавлено через 12 минут и 20 секунд
Ещё вопрос:

Есть такой параметр dwCompKey.

Правильно ли он используется?

Автор: NickAnd 27.3.2010, 19:39
Спасибо за ссылку!

В моем случае наверно нужно попробовать WSAGetOverlappedResult.

Добавлено через 4 минуты и 48 секунд
Цитата(Демо @ 27.3.2010,  19:15)
Ещё вопрос:

Есть такой параметр dwCompKey.

Правильно ли он используется?

Не очень понял вопрос... 

Поэтому отвечу вопросом на вопрос: Как правильно его использовать?

Я в этом параметре храню данные (структуру), которые связаны с открытым сокетом (сокет, дата-время открытия, дата-время последней операции, данные полученные последней операцией WSARecv  и т.п.)

Автор: Демо 27.3.2010, 20:22
Цитата(NickAnd @  27.3.2010,  19:39 Найти цитируемый пост)
Не очень понял вопрос... 


Я имел ввиду следущее:
Поток, который получает управление, ничего не знает о том, зачем и кто его пробудил от спячки.
После выполнения GetQueuedCompletionStatus в этом потоке получаем WSAOverlapped-структуру и dwCompKey, связанные с запросом, реакция на который произошла.

В этот момент у тебя никаких коллизий не возникает, путаницы с объектами?


Цитата(NickAnd @  27.3.2010,  19:39 Найти цитируемый пост)
Я в этом параметре храню данные (структуру), которые связаны с открытым сокетом (сокет, дата-время открытия, дата-время последней операции, данные полученные последней операцией WSARecv  и т.п.)


Ну в принципе так и есть.

Я обычно создаю класс, в котором и хранится вся связанная с сеансом информация, методы обработки, связанные с объетом.
Ссылку на экземпляр класса и передаю.

Кстати, обнулять каждый раз структуру не нужно, если тебе нужны данные, которые она содержит.
Нужно только правильно обрабатывать и устанавливать поле hEvent.

Автор: NickAnd 27.3.2010, 22:39
Цитата(Демо @ 27.3.2010,  20:22)
В этот момент у тебя никаких коллизий не возникает, путаницы с объектами?


Нет, путаницы не возникает. Все данные которые нужны для идентификации "кто это" у меня хранятся в структуре (классе) на который указывает dwCompKey

Добавлено через 14 минут и 19 секунд
Цитата(Демо @ 27.3.2010,  20:22)
Кстати, обнулять каждый раз структуру не нужно, если тебе нужны данные, которые она содержит.
Нужно только правильно обрабатывать и устанавливать поле hEvent.

Если возможно по поводу hEvent поподробней.

На сейчас отработанные "временные" WSAOverlapped-структуры складываю в отдельный список (предварительно освобождая буфер WSABUF -- он у меня прицепом к структуре идет), чтобы потом освободить занятую под ними память (возможно отдельным thread-ом "чистильщиком").

Но в какой момент освобождать собственно TWSAOverlapped пока не понимаю.

Дело в том, что даже освобождение "основных" WSAOverlapped-структур при закрытии сокета клиентом (GetQueuedCompletionStatus = false или lpNumberOfBytesTransferred = 0) приводит к ситуации, когда имеем изменения в освобожденном блоке.

Мне кажется, что должен быть механизм, который однозначно гарантирует, что "заявленная" WSAOverlapped-структура в одном из вызовов WSARecv, WSASSend системой больше изменяться не будет...

Гуглю... пока безрезультатно... 
Нашел только на MSDN:

The closesocket function closes a socket. Use it to release the socket descriptor s so that further references to s  fail with the error WSAENOTSOCK. If this is the last reference to an underlying socket, the associated naming information and queued data are discarded. Any pending blocking, asynchronous calls issued by any thread in this process are canceled without posting any notification messages.

Any pending overlapped send and receive operations ( WSASend/ WSASendTo/ WSARecv/ WSARecvFrom with an overlapped socket) issued by any thread in this process are also canceled. Any event, completion routine, or completion port action specified for these overlapped operations is performed. The pending overlapped operations fail with the error status WSA_OPERATION_ABORTED.

An application should not assume that any outstanding I/O operations on a socket will all be guaranteed to completed when closesocket returns. The closesocket function will initiate cancellation on the outstanding I/O operations, but that does not mean that an application will receive I/O completion for these I/O operations by the time the closesocket function returns. Thus, an application should not cleanup any resources (WSAOVERLAPPED structures, for example) referenced by the outstanding I/O requests until the I/O requests are indeed completed. 


А как узнать когда ж они "are indeed completed" ?

Автор: Демо 28.3.2010, 01:37
Цитата(NickAnd @  27.3.2010,  22:39 Найти цитируемый пост)
А как узнать когда ж они "are indeed completed" ?


Выполни предварительно shutdown...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)