Пишу высокопроизводительный сервер на 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
Здравствуйте, 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
Здравствуйте, 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.
Думаю, исходя из этих пунктов CancelThreadpoolIo нужно звать после любого AcceptEx c WsaGetLastError() != ERROR_IO_PENDING. Хотя сам вистовый пул не использовал, только IOCP на своих тредах.