2015-03-09 1 views
0

Я заметил странное поведение при вызове closesocket(). Если я создаю поток, который вызывает recv(), то closesocket() отправит RST пакет на другую сторону. Однако, если я не создаю поток приема, тогда closesocket() выполнит изящное отключение (4-стороннее рукопожатие).Странное поведение closesocket()

Следующий код вызовет closesocket() отправить RST пакет:

#include <WinSock2.h> 
#pragma comment(lib, "ws2_32.lib") 
#include <process.h> 

unsigned int __stdcall thread(void *s) 
{ 
    char buffer[1024]; 
    recv((SOCKET)s, buffer, 1024, 0); 

    return 0; 
} 

int main() 
{ 
    WSADATA wsa; 
    WSAStartup(MAKEWORD(2, 2), &wsa); 
    SOCKET s = socket(AF_INET, SOCK_STREAM, 0); 

    sockaddr_in addr; 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = inet_addr("173.194.116.18"); 
    addr.sin_port = htons(80); 
    connect(s, (sockaddr*)&addr, sizeof(addr)); 

    // Start thread 
    _beginthreadex(0, 0, thread, (void*)s, 0, 0); 
    Sleep(1000); // give thread some time to start 

    // RST packet will be sent (if you remove the receive thread then a graceful disconnection will be performed) 
    closesocket(s); 

    return 0; 
} 

Примечание: Я использую блокирующие сокеты.

+0

Возможно ли, что ваш буфер недостаточно велик, чтобы прочитать весь отклик в одном чтении? Я предполагаю, что вы частично читали. – Freddy

+2

[closesocket] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms737582.aspx): * «Клиент Winsock никогда не должен выпускать ** closesocket ** на * s * одновременно с другим Winsock function. "* – IInspectable

+0

@IInspectable Поэтому мне нужно убедиться, что никакая другая функция Winsock не использует' s', когда я вызываю 'closesocket()'? –

ответ

1

Если клиент отправляет более одного байта, сервер будет считывать первый байт и звонить с данными в своей очереди приема, вызывая отправку RST клиенту. Клиент будет заблокирован при вызове recv(), ожидающем ответа от сервера . Получив RST, DieWithError() сообщает о проблеме соединения с сервером. Таким образом, выключение может быть использовано до вызова close. Я надеюсь, что эта статья поможет вам связать RST http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf

+2

Укажите контекст для ссылки, которую вы опубликовали (см. [Как написать хороший ответ?] (Http://stackoverflow.com/help/how-to-answer)). Если ресурс исчезает, ответ больше не дает никакого значения. – IInspectable

+0

Спасибо @ IInpectable за указание на улучшение :) – add2c

+0

Если клиент отправляет более одного байта, сервер разблокирует и почти наверняка прочитает их все в одно и то же время. – EJP

Смежные вопросы