GetQueuedCompletionStatus 接收旧数据

GetQueuedCompletionStatus recevies old data

如果您尝试 运行 我的脚本,您会发现 GetQueuedCompletionStatus 不会在第二次 wsarecv 调用后阻塞。我不明白为什么这段代码不起作用。 代码有点乱,但很简单,所以应该可以。

服务器:

#undef UNICODE
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include <iostream>

using namespace std;

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")



WSADATA wsaData;
int iResult;

HANDLE CompletionPort;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;

OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[200];
DWORD BytesSEND;
DWORD BytesRECV;
DWORD RecvBytes;

sockaddr_in local;

DWORD Flags;
int iSendResult;


void serverWorkerThread() {

OVERLAPPED lpol2;
DWORD Flags = 0;
DWORD BytesTransferred;
DWORD is = 0;
DWORD sentBytes;
bool kage = 0;
WSABUF wsabuf;
CHAR Buffer2[200];


while (true) {

    if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, &is, (LPOVERLAPPED*)& lpol2, INFINITE) == 0)

    {

        printf("GetQueuedCompletionStatus() failed with error %d\n", GetLastError());



    }

    else

        printf("GetQueuedCompletionStatus() is OK!\n");

    cout << DataBuf.buf << endl;

    cout << is;
    DataBuf.len = 14;
    ZeroMemory(&(Overlapped), sizeof(OVERLAPPED));





        if (WSASend(ClientSocket, &DataBuf, 1, &sentBytes, 0,

            NULL, NULL) == SOCKET_ERROR)

        {

            if (WSAGetLastError() != ERROR_IO_PENDING)

            {

                printf("WSASend() failed with error %d\n", WSAGetLastError());



            }

        }

        else

            printf("WSASend() is OK!\n");


    ZeroMemory(&(lpol2), sizeof(OVERLAPPED));

    wsabuf.buf = Buffer2;
    wsabuf.len = 200;
    BytesTransferred = 0;
    is = 0;


    ZeroMemory(&(Overlapped), sizeof(OVERLAPPED));
    Flags = 0;
    if (WSARecv(ClientSocket, &wsabuf, 1, &RecvBytes, &Flags, &Overlapped, NULL) == SOCKET_ERROR)

    {

        if (WSAGetLastError() != ERROR_IO_PENDING)

        {

            printf("WSARecv() failed with error %d\n", WSAGetLastError());


        }

    }

    else printf("WSARecv() is OK!\n");


}

}

int __cdecl main(void)
{


// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed with error: %d\n", iResult);
    return 1;
}

CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);



//Now we populate the sockaddr_in structure
local.sin_family = AF_INET; //Address family
local.sin_addr.s_addr = INADDR_ANY; //Wild card IP address
local.sin_port = htons((u_short)20248); //port to use


// Create a SOCKET for connecting to server
ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ListenSocket == INVALID_SOCKET) {
    printf("socket failed with error: %ld\n", WSAGetLastError());
    WSACleanup();
    return 1;
}

// Setup the TCP listening socket




iResult = bind(ListenSocket, (sockaddr*)& local, sizeof(local));
if (iResult == SOCKET_ERROR) {
    printf("bind failed with error: %d\n", WSAGetLastError());

    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}



iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
    printf("listen failed with error: %d\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}
DataBuf.len = 2000;
DataBuf.buf = Buffer;
thread t1(serverWorkerThread);
t1.detach();

DWORD iss = 34543;



while (TRUE)

{

    ClientSocket = WSAAccept(ListenSocket, NULL, NULL, NULL, 0);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }




    if (CreateIoCompletionPort((HANDLE)ClientSocket, CompletionPort, 43343, 0) == NULL)

    {

        printf("CreateIoCompletionPort() failed with error %d\n", GetLastError());

        return 1;

    }

    else

        printf("CreateIoCompletionPort() is OK!\n");






    Flags = 0;
    if (WSARecv(ClientSocket, &DataBuf, 1, &RecvBytes, &Flags, &Overlapped, NULL) == SOCKET_ERROR)

    {

        if (WSAGetLastError() != ERROR_IO_PENDING)

        {

            printf("WSARecv() failed with error %d\n", WSAGetLastError());

            return 1;

        }

    }

    else printf("WSARecv() is OK!\n");



}








// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
    printf("shutdown failed with error: %d\n", WSAGetLastError());
    closesocket(ClientSocket);
    WSACleanup();
    return 1;
}

// cleanup
closesocket(ClientSocket);
WSACleanup();

return 0;
}

客户:

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>



// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

using namespace std;

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int __cdecl main(int argc, char** argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
SOCKADDR_IN          ServerAddr;

// Server/receiver port to connect to

unsigned int         Port = 20248;
//struct addrinfo* result = NULL,
//  * ptr = NULL,
//  hints;
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;

cout << sendbuf << endl;

// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed with error: %d\n", iResult);
    return 1;
}





    // Create a SOCKET for connecting to server
    ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 2;
    }



    // IPv4

    ServerAddr.sin_family = AF_INET;
    // Port no.
    ServerAddr.sin_port = htons(Port);
    // The IP address
    ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");


    // Connect to server.
    iResult = connect(ConnectSocket, (SOCKADDR*)& ServerAddr, sizeof(ServerAddr));
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
        printf("socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 3;
    }





if (ConnectSocket == INVALID_SOCKET) {
    printf("Unable to connect to server!\n");
    WSACleanup();
    return 4;
}

// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
    printf("send failed with error: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 5;
}

printf("Bytes Sent: %ld\n", iResult);

// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
    printf("shutdown failed with error: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 6;
}

// Receive until the peer closes the connection
do {

    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0)
        printf("Bytes received: %d\n", iResult);
    else if (iResult == 0)
        printf("Connection closed\n");
    else
        printf("recv failed with error: %d\n", WSAGetLastError());

} while (iResult > 0);

// cleanup
closesocket(ConnectSocket);
WSACleanup();

return 0;



}

我发现了问题: 客户端关闭了使 GetQueuedCompletionStatus 保持 运行

的连接