Правильная логика AcceptEx и CreateThreadpoolIo
От: Gorilla  
Дата: 17.08.11 13:51
Оценка:
Пишу высокопроизводительный сервер на Thread Pool API появившеся в Vista. Создаю сокет, ассоциирую с ним каллбек через CreateThreadpoolIo, делаю StartThreadpoolIo и вызываю AcceptEx чтобы принять соединение клиента.
AcceptEx может вернуть FALSE && WSAGetLastError() == ERROR_IO_PENDING — это обычная ситуация, при подключении клиента вызывается мой каллбек, также может вернуть FALSE && WSAGetLastError() != ERROR_IO_PENDING — значит произошла ошибка и надо вызвать CancelThreadpoolIo, мой каллбек не вызывается.
Вопрос: что делать если AcceptEx вернул TRUE? Вызывается ли каллбек, нужно ли делать CancelThreadpoolIo? MSDN не говорит насчет этого ничего определенного, получить такую ситуацию в своем коде мне не удалось, но обрабатывать ее надо.
Re: Правильная логика AcceptEx и CreateThreadpoolIo
От: 11molniev  
Дата: 17.08.11 18:05
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>Пишу высокопроизводительный сервер на Thread Pool API появившеся в Vista. Создаю сокет, ассоциирую с ним каллбек через CreateThreadpoolIo, делаю StartThreadpoolIo и вызываю AcceptEx чтобы принять соединение клиента.

G>AcceptEx может вернуть FALSE && WSAGetLastError() == ERROR_IO_PENDING — это обычная ситуация, при подключении клиента вызывается мой каллбек, также может вернуть FALSE && WSAGetLastError() != ERROR_IO_PENDING — значит произошла ошибка и надо вызвать CancelThreadpoolIo, мой каллбек не вызывается.
G>Вопрос: что делать если AcceptEx вернул TRUE? Вызывается ли каллбек, нужно ли делать CancelThreadpoolIo? MSDN не говорит насчет этого ничего определенного, получить такую ситуацию в своем коде мне не удалось, но обрабатывать ее надо.

msdn:
The AcceptEx function accepts a new connection, returns the local and remote address, and receives the first block of data sent by the client application.
If no error occurs, the AcceptEx function completed successfully and a value of TRUE is returned.

Если между bind & AcceptEx или между AcceptEx & AcceptEx запрос на соединение уже поступил — функция выполняеться как синхронная. Callback не вызываеться. sAcceptSocket — сокет для подключеного клиента. В lpdwBytesReceived возможно возвращена уже первая порция данных от него.

В принципе можите проверять только WSAGetLastError:
если ERROR_IO_PENDING — будет вам callback и обрабатывать надо все там
если ERROR_SUCCESS — Callback-а не будет, успешное соединение нужно обработать уже сейчас
иначе — ошибка, callback-а не будет, обрабатывать соединение не надо.

PS. В madn по AcceptEx пример какой-то странный. Лучше им не руководствоваться.
Re: Правильная логика AcceptEx и CreateThreadpoolIo
От: Ligen Украина http://zone-of-ambiguity.blogspot.com/
Дата: 17.08.11 21:54
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>Вопрос: что делать если AcceptEx вернул TRUE? Вызывается ли каллбек, нужно ли делать CancelThreadpoolIo? MSDN не говорит насчет этого ничего определенного, получить такую ситуацию в своем коде мне не удалось, но обрабатывать ее надо.


Ну что-то MSDN все-таки говорит:

To prevent memory leaks, you must call the CancelThreadpoolIo function for either of the following scenarios:

* An overlapped (asynchronous) I/O operation fails (that is, the asynchronous I/O function call returns failure with an error code other than ERROR_IO_PENDING).
* An asynchronous I/O operation returns immediately with success and the file handle associated with the I/O completion object has the notification mode FILE_SKIP_COMPLETION_PORT_ON_SUCCESS. The file handle will not notify the I/O completion port and the associated I/O callback function will not be called.

msdn:CancelThreadpoolIo

Думаю, исходя из этих пунктов CancelThreadpoolIo нужно звать после любого AcceptEx c WsaGetLastError() != ERROR_IO_PENDING. Хотя сам вистовый пул не использовал, только IOCP на своих тредах.
Viva el Junta Militar! Viva el Presidente!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.