GetQueuedCompletionStatus получает старые данные - PullRequest
0 голосов
/ 23 мая 2019

Если вы попытаетесь запустить мой скрипт, вы увидите, что 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;



}

1 Ответ

0 голосов
/ 23 мая 2019

Я обнаружил проблему: клиенты выкрикивают соединение, которое заставило GetQueuedCompletionStatus продолжать работать

...