本文介绍了ReleaseSemaphore 返回错误 6(句柄无效)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用两个线程来运行服务器和客户端.我使用信号量来阻止客户端线程在设置服务器之前执行过多操作(ListenSocket 等).

当服务器足够远时,我使用 ReleaseSemaphore() 但它返回一个 Invalid Handle 错误.我读到有许多可能的问题可能是此错误的根源.

确切的行是 if (ReleaseSemaphore(semaphore, 1, NULL)){},它可以在 Server.cpp 文件的大约 55% 处找到

Header.h:

#define WIN32_LEAN_AND_MEAN#include #include #include #include #include #include unsigned int __stdcall servermain(void*);unsigned int __stdcall clientmain(void*);静态句柄信号量;

Source.cpp:

#include "Header.h"int main(int argc, char* argv[]){处理服务器句柄,客户端句柄;信号量 = 创建信号量(空值,0,//初始计数1,//最大计数空值);如果(信号量 == NULL){printf("创建信号量错误:%d\n", GetLastError());返回 1;}/*调用客户端和服务器文件中的方法*/serverHandle = (HANDLE)_beginthreadex(0, 0, &ser​​vermain, 0, 0, 0);clientHandle = (HANDLE)_beginthreadex(0, 0, &clientmain, 0, 0, 0);WaitForSingleObject(serverHandle, INFINITE);WaitForSingleObject(clientHandle, INFINITE);关闭句柄(服务器句柄);关闭句柄(客户端句柄);关闭句柄(信号量);返回0;}

Server.cpp:

#include "Header.h"#pragma 注释(lib,Ws2_32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT "27015"unsigned int __stdcall servermain(void* data){printf("服务器启动.线程:%i\n", GetCurrentThreadId());WSADATA wsaData;内部结果;SOCKET ListenSocket = INVALID_SOCKET;SOCKET ClientSocket = INVALID_SOCKET;结构地址信息*结果=空,提示;int iSendResult;char recvbuf[DEFAULT_BUFLEN];int recvbuflen = DEFAULT_BUFLEN;//初始化 WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);//启动Winsock DLL的使用如果(结果!= 0){printf("%i 服务器:\t", GetCurrentThreadId());printf("WSAStartup 失败,错误:%d\n", iResult);返回 1;}////////////////////////////////////////为服务器创建一个套接字////////////////////////////////////////ZeroMemory(&hints, sizeof(hints));提示.ai_family = AF_INET;提示.ai_socktype = SOCK_STREAM;提示.ai_protocol = IPPROTO_TCP;提示.ai_flags = AI_PASSIVE;//解析服务器要使用的本地地址和端口iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);如果(结果!= 0){printf("%i 服务器:\t", GetCurrentThreadId());printf("getaddrinfo 失败,错误:%d\n", iResult);WSACleanup();返回 1;}//为服务器创建一个 SOCKET 来监听客户端连接ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);如果(ListenSocket == INVALID_SOCKET){printf("%i 服务器:\t", GetCurrentThreadId());printf("socket failed with error: %ld\n", WSAGetLastError());freeaddrinfo(结果);WSACleanup();返回 1;}////////////////////////绑定一个套接字//////////////////////////设置 TCP 监听套接字iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);如果(iResult == SOCKET_ERROR){printf("%i 服务器:\t", GetCurrentThreadId());printf("绑定失败,错误:%d\n", WSAGetLastError());freeaddrinfo(结果);closesocket(ListenSocket);WSACleanup();返回 1;}字符答案 = 'y';//字符答案[8];//字符 *answer = "";做{printf("%i 服务器:\t", GetCurrentThreadId());printf("你愿意等待客户吗?(Y/N)\t");答案 = getchar();//fgets(answer, 1, stdin);printf("%c\n", 答案);} while (answer != 'y' && answer != 'n');//双引号 "" 用于 c 字符串.单引号 '' 用于字符.如果(答案=='n'){返回 1;}else printf("%i 服务器:\t监听客户端...\n", GetCurrentThreadId());freeaddrinfo(结果);printf("信号量值:%i\n", 信号量);//现在服务器正在运行,向信号量发出信号以允许客户端连接.if (ReleaseSemaphore(semaphore, 1, NULL))//ReleaseSemaphore() 返回一个布尔值{printf("%i 服务器:信号量已释放\n", GetCurrentThreadId());}别的{printf("服务器发布信号量错误:%d\n", GetLastError());printf("服务器信号量值:%i\n", 信号量);返回 1;}/////////////////////////////监听套接字/////////////////////////////iResult = listen(ListenSocket, SOMAXCONN);如果(iResult == SOCKET_ERROR){printf("%i 服务器:\t", GetCurrentThreadId());printf("监听失败,错误:%ld\n", WSAGetLastError());closesocket(ListenSocket);WSACleanup();返回 1;}/////////////////////////////接受连接///////////////////////////////接受一个客户端套接字ClientSocket = accept(ListenSocket, NULL, NULL);如果(ClientSocket == INVALID_SOCKET){printf("%i 服务器:\t", GetCurrentThreadId());printf("接受失败:%d\n", WSAGetLastError());closesocket(ListenSocket);WSACleanup();返回 1;}//不再需要服务器套接字closesocket(ListenSocket);//如果允许多个客户端,则需要更改此设置////////////////////////////////////////////////在服务器上接收和发送数据//////////////////////////////////////////////////接收直到对端关闭连接做 {iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);如果 (iResult > 0) {printf("%i 服务器:\t", GetCurrentThreadId());printf("接收到的字节数:%d\n", iResult);//将缓冲区回显给发送方iSendResult = send(ClientSocket, recvbuf, iResult, 0);如果(iSendResult == SOCKET_ERROR){printf("发送失败:%d\n", WSAGetLastError());closesocket(ClientSocket);//如果某些东西没有正确发送,为什么要关闭套接字?WSACleanup();返回 1;//杀死main()}printf("发送的字节数:%d\n", iSendResult);}否则如果(iResult == 0)printf("连接关闭...\n");别的 {printf("接收失败,错误:%d\n", WSAGetLastError());closesocket(ClientSocket);WSACleanup();//函数终止使用 Winsock 2 DLL (Ws2_32.dll)返回 1;}} while (iResult > 0);//关闭发送的一半连接,因为将不再发送数据iResult = 关机(ClientSocket,SD_SEND);如果(iResult == SOCKET_ERROR){printf("%i 服务器:\t", GetCurrentThreadId());printf("关机失败,错误:%d\n", WSAGetLastError());closesocket(ClientSocket);WSACleanup();返回 1;}//清理closesocket(ClientSocket);WSACleanup();_endthreadex(0);//在线程内结束线程.返回0;}

Client.cpp:

#include "Header.h"#pragma 注释(lib,Ws2_32.lib")#pragma 注释(lib,Mswsock.lib")#pragma 注释(lib,AdvApi32.lib")#define DEFAULT_BUFLEN 512#define DEFAULT_PORT "27015"unsigned int __stdcall clientmain(void* data){printf("客户端启动.线程:%i\n", GetCurrentThreadId());WSADATA wsaData;SOCKET ConnectSocket = INVALID_SOCKET;struct addrinfo *result = NULL,*ptr = NULL,提示;char *sendbuf = "这是一个测试";char recvbuf[DEFAULT_BUFLEN];内部结果;int recvbuflen = DEFAULT_BUFLEN;//验证参数/*if (argc != 2) {printf("用法:%s 服务器名称\n", argv[0]);返回 1;}*///初始化 WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);如果(结果!= 0){printf("%i Client:\t", GetCurrentThreadId());printf("WSAStartup 失败,错误:%d\n", iResult);返回 1;}printf("客户端 winsock 已初始化\n");ZeroMemory(&hints, sizeof(hints));提示.ai_family = AF_UNSPEC;提示.ai_socktype = SOCK_STREAM;提示.ai_protocol = IPPROTO_TCP;//解析服务器地址和端口/*iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);如果(结果!= 0){printf("getaddrinfo 失败,错误:%d\n", iResult);WSACleanup();返回 1;}*/printf("%i 客户端:信号量前\n", GetCurrentThreadId());//等待服务器启动并运行布尔值 = TRUE;同时(续){DWORD returnval = WaitForSingleObject(semaphore, 0L);//0 对 0L ?//printf("信号量值:%i\n", semaphore);开关(返回值){//信号量对象已发出信号.案例 WAIT_OBJECT_0:printf("线程 %d: 等待成功\n", GetCurrentThreadId());休息;//信号量未发出信号,因此发生超时.案例 WAIT_TIMEOUT:printf("线程 %d: 等待超时\n", GetCurrentThreadId());休息;}}printf("%i 客户端:在信号量之后\n", GetCurrentThreadId());//尝试连接到一个地址,直到成功for (ptr = 结果;ptr != NULL;ptr = ptr->ai_next) {//创建一个用于连接服务器的 SOCKETConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);如果(ConnectSocket == INVALID_SOCKET){printf("%i Client:\t", GetCurrentThreadId());printf("socket failed with error: %ld\n", WSAGetLastError());WSACleanup();返回 1;}//连接到服务器.iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);如果(iResult == SOCKET_ERROR){closesocket(ConnectSocket);ConnectSocket = INVALID_SOCKET;继续;}休息;}freeaddrinfo(结果);如果(ConnectSocket == INVALID_SOCKET){printf("%i Client:\t", GetCurrentThreadId());printf("无法连接到服务器!\n");WSACleanup();返回 1;}//发送初始缓冲区iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);如果(iResult == SOCKET_ERROR){printf("%i Client:\t", GetCurrentThreadId());printf("发送失败,错误:%d\n", WSAGetLastError());closesocket(ConnectSocket);WSACleanup();返回 1;}printf("发送的字节数:%ld\n", iResult);//关闭连接,因为不会发送更多数据iResult = 关机(ConnectSocket,SD_SEND);如果(iResult == SOCKET_ERROR){printf("%i Client:\t", GetCurrentThreadId());printf("关机失败,错误:%d\n", WSAGetLastError());closesocket(ConnectSocket);WSACleanup();返回 1;}//接收直到对端关闭连接做 {printf("%i Client:\t", GetCurrentThreadId());iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);如果 (iResult > 0)printf("接收到的字节数:%d\n", iResult);否则如果(iResult == 0)printf("连接关闭\n");别的printf("接收失败,错误:%d\n", WSAGetLastError());} while (iResult > 0);//清理closesocket(ConnectSocket);WSACleanup();printf("%i Client:\t", GetCurrentThreadId());printf("\n返回关闭.\n");getchar();//允许用户在关闭前看屏幕_endthreadex(0);返回0;}
解决方案

您在 header.h 中将 semaphore 声明为 static HANDLE.这意味着每个包含 "header.h" 的源模块都将拥有该变量的自己的副本.因此,main.cpp 中保存 Windows 信号量句柄的 semaphoreserver.cpp 中引用的 semaphore 是不同的变量.>

去掉header.h中声明的static,替换为extern,并在中添加定义main.cpp.

I'm trying to use two threads to run a server and a client.I use a semaphore to block the client thread from doing too much before the server has been set up (ListenSocket, etc.).

When The server gets far enough, I use ReleaseSemaphore() but it returns an Invalid Handle error.I've read that there are many possible issues which can be the source of this error.

The exact line is if (ReleaseSemaphore(semaphore, 1, NULL)){} which can be found about 55% of the way into the Server.cpp file

Header.h:

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>

unsigned int __stdcall servermain(void*);

unsigned int __stdcall clientmain(void*);

static HANDLE semaphore;

Source.cpp:

#include "Header.h"

int main(int argc, char* argv[])
{
    HANDLE serverHandle, clientHandle;

    semaphore = CreateSemaphore(
        NULL,
        0,  //initial count
        1,  //max count
        NULL);

    if (semaphore == NULL){
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }


    /*call to the methods in the Client and Server files*/
    serverHandle = (HANDLE)_beginthreadex(0, 0, &servermain, 0, 0, 0);
    clientHandle = (HANDLE)_beginthreadex(0, 0, &clientmain, 0, 0, 0);

    WaitForSingleObject(serverHandle, INFINITE);
    WaitForSingleObject(clientHandle, INFINITE);

    CloseHandle(serverHandle);
    CloseHandle(clientHandle);
    CloseHandle(semaphore);

    return 0;
}

Server.cpp:

#include "Header.h"

#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

unsigned int __stdcall servermain(void* data)
{
    printf("SERVER STARTED. Thread: %i\n", GetCurrentThreadId());

    WSADATA wsaData;
    int iResult;

    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo
        *result = NULL,
        hints;

    int iSendResult;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); //initiates the use of the Winsock DLL
    if (iResult != 0) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }


    //////////////////////////////////////
    // Creating a Socket for the Server //
    //////////////////////////////////////

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the local address and port to be used by the server
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }


    // Create a SOCKET for the server to listen for client connections
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }


    //////////////////////
    // Binding a Socket //
    //////////////////////

    // Setup the TCP listening socket
    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    char answer = 'y'; // char answer[8]; // char *answer = "";
    do{
        printf("%i Server:\t", GetCurrentThreadId());

        printf("Would you like to wait for client?(Y/N)\t");

        answer = getchar(); // fgets(answer, 1, stdin);
        printf("%c\n", answer);
    } while (answer != 'y' && answer != 'n'); // double quotes "" are for c-strings. single quotes '' are for chars.

    if (answer == 'n'){
        return 1;
    }
    else printf("%i Server:\tListening for a client...\n", GetCurrentThreadId());

    freeaddrinfo(result);

    printf("Semaphore value: %i\n", semaphore);

    //Now that the server is running, signal the semaphore to allow client to connect.
    if (ReleaseSemaphore(semaphore, 1, NULL)) //ReleaseSemaphore() returns a bool value
    {
        printf("%i Server: Semaphore Released\n", GetCurrentThreadId());
    }
    else
    {
        printf("Server Release Semaphore error: %d\n", GetLastError());
        printf("Server Semaphore value: %i\n", semaphore);
        return 1;
    }


    ///////////////////////////
    // Listening on a Socket //
    ///////////////////////////

    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("Listen failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ////////////////////////////
    // Accepting a Connection //
    ////////////////////////////

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("accept failed: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket); // This will need to be changed if multiple clients shall be allowed

    //////////////////////////////////////////////
    // Receiving and Sending Data on the Server //
    //////////////////////////////////////////////

    // Receive until the peer shuts down the connection
    do {

        iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            printf("%i Server:\t", GetCurrentThreadId());

            printf("Bytes received: %d\n", iResult);

            // Echo the buffer back to the sender
            iSendResult = send(ClientSocket, recvbuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed: %d\n", WSAGetLastError());
                closesocket(ClientSocket); //why close a socket if something doesn't send correctly?
                WSACleanup();
                return 1; //kills main()
            }
            printf("Bytes sent: %d\n", iSendResult);
        }
        else if (iResult == 0)
            printf("Connection closing...\n");
        else {
            printf("recv failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup(); //function terminates use of the Winsock 2 DLL (Ws2_32.dll)
            return 1;
        }

    } while (iResult > 0);

    // shutdown the send half of the connection since no more data will be sent
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("%i Server:\t", GetCurrentThreadId());
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

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

    _endthreadex(0); //end thread within the thread.
    return 0;
}

Client.cpp:

#include "Header.h"

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

unsigned int __stdcall clientmain(void* data)
{
    printf("CLIENT STARTED. Thread: %i\n", GetCurrentThreadId());

    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;

    // Validate the parameters
    /*if (argc != 2) {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }*/


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

    printf("Client winsock initialized\n");

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    /*iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }*/


    printf("%i Client: before semaphore\n", GetCurrentThreadId());
    //Wait for Server to be up and running

    bool cont = TRUE;
    while (cont)
    {
        DWORD returnval = WaitForSingleObject(semaphore, 0L); // 0 vs 0L ?

        //printf("Semaphore value: %i\n", semaphore);

        switch (returnval)
        {
            // The semaphore object was signaled.
            case WAIT_OBJECT_0:
                printf("Thread %d: wait succeeded\n", GetCurrentThreadId());

                break;

                // The semaphore was nonsignaled, so a time-out occurred.
            case WAIT_TIMEOUT:
                printf("Thread %d: wait timed out\n", GetCurrentThreadId());
                break;
        }
    }

    printf("%i Client: after semaphore\n", GetCurrentThreadId());

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("%i Client:\t", GetCurrentThreadId());
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("%i Client:\t", GetCurrentThreadId());
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

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

    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("%i Client:\t", GetCurrentThreadId());
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {
        printf("%i Client:\t", GetCurrentThreadId());

        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();

    printf("%i Client:\t", GetCurrentThreadId());
    printf("\nReturn to close.\n");
    getchar(); //allow user to do see screen before shutting down

    _endthreadex(0);
    return 0;
}
解决方案

You declare semaphore as a static HANDLE in header.h. That means that every source module that includes "header.h" will have its own copy of that variable. Thus, the semaphore in main.cpp that holds the Windows semaphore handle is a different variable than the semaphore referenced in server.cpp.

Remove the static from the declaration in header.h, replace it with extern, and add a definition for it in main.cpp.

这篇关于ReleaseSemaphore 返回错误 6(句柄无效)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 14:47