Есть вопрос по работе с сокетом через порты завершения ввода
От: s3dworld Россия  
Дата: 26.09.11 12:32
Оценка:
Всем доброго дня!

Создаю асинхронный сокет:

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() передаст управление. И вопрос к Вам, что она мне вернёт?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.