Всем доброго дня!
Создаю асинхронный сокет:
SOCKET client=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);
if(client==INVALID_SOCKET) return error;
Создаю порт и связываю с сокетом:
HANDLE port=CreateIoCompletionPort(client,0,0,1);
if(!port) return error;
Предположим я уже подключился через одну из трёх функций и вот уже хочу отправить данные. Для этого я буду использовать WSASend():
int result=0;
char buffer[32];
// Заполняю буфер данными
WSABUF bufferSend;
bufferSend.buf=buffer;
bufferSend.len=32;
DWORD sendBytes=0;
MYOVERLAPPED overlapped; // Унаследованная от WSAOVERLAPPED
overlapped.type=TYPE_SEND;
result=WSASend(client,&bufferSend,1,&sendBytes,0,&overlapped,0);
// Проверка значения в result
Что же тут может произойти? Во-первых, может возникнуть ошибка (сеть недоступна) или штатная ситуация, когда соединение было завершено (например завершено удалённой стороной). Во-вторых, возможны ситуации, когда функция тут же передаст управление (я полагаю именно в данной ситуации sendBytes вернёт столько, сколько нам нужно было передать и ни на байт меньше, я прав?). В-третьих: если операция не может быть выполнена немедленно, то функция вернёт нам WSA_IO_PENDING. Да, оговорюсь, не функция вернёт, а код ошибки вернёт, при возвращении функцией значения SOCKET_ERROR. Но вот не понятно мне в каком случае может вернуться WSA_OPERATION_ABORTED. Мы же только запустили функцию, она должна мгновенно передать управление. Это что, если вдруг за это мгновение я из другого потока отменил перекрёстную (асинхронную) операцию, то вот это и произойдёт? Что-то мне кажется маловероятным возникновение такой ситуации. Или я ошибаюсь?
Но больше всего меня интересует следующее, если мы получили WSA_IO_PENDING, то значит ли это, что при ожидании завершения:
bool isExit=false;
DWORD numberBytes=0;
PULONG_PTR key=0;
MYOVERLAPPED overlapped;
while(!isExit)
{
GetQueuedCompletionStatus(port,&numberBytes,&key,&overlapped,INFINITY);
// Обработка
}
В numberBytes всегда будет такое значение, сколько мы хотели отправить? Просто в противном случае было бы больше кода отслеживания. Хотя я сам уже думаю что всё таки получить тут я могу разное число, но могу ли я получить тут 0 и в каких случаях?
Мне не понятно поведение системы в такой вот ситуации: я вызываю WSASend() и прошу её передать 75 МБ (размер выбрал для наглядности примера). Соединение с сокетом существует, операция не может быть выполнена мгновенно, в результате я получу ошибку WSA_IO_PENDING (собственно это успешная ошибка). Я занимаюсь своими делами, а система за меня отсылает данные (видимо тут я только должен позаботиться чтобы буфер с отсылаемыми данными не накрылся при выходе из области видимости, в которой вызывалась WSASend(), то есть сделать его не на стеке как в приведённом выше примере). Через 40 секунд сервер (а может и я сам) завершает соединение со мной, но я успел передать только 13 МБ. Функция GetQueuedCompletionStatus() передаст управление. И вопрос к Вам, что она мне вернёт?