简体   繁体   English

Visual C ++通过线程发送消息

[英]Visual C++ Sending message across thread

I am writting a small server application which has ServerSocket object waiting for and create connection socket. 我正在编写一个具有ServerSocket对象的小型服务器应用程序,并创建连接套接字。 Each connection has a SocketListener and a SocketSender for transfering data. 每个连接都有一个用于传输数据的SocketListener和SocketSender。

Each SocketListener is a separate thread. 每个SocketListener是一个单独的线程。 When a connection is disconnect by client, SocketListener send a message to ServerSocket notify that it is closing, so that ServerSocket can clear the handle for that connection from a list. 当客户端断开连接时,SocketListener会向ServerSocket发送一条消息,通知其正在关闭,以便ServerSocket可以从列表中清除该连接的句柄。

However, don't know why the message is not received by SocketListener thread. 但是,不知道为什么SocketListener线程未收到该消息。 I have tried to narrow down the message filter, but no luck. 我试图缩小邮件过滤器的范围,但是没有运气。 Could someone help me with this. 有人可以帮我这个忙。

DWORD ServerSocket::m_ThreadFunc() {
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed\n");
    return 1;
}

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 server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT_STR, &hints, &result);
if (iResult != 0) {
    printf("getaddrinfo failed\n");
    WSACleanup();
    return 1;
}

// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
    printf("socket failed\n");
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}

// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
    printf("bind failed\n");
    freeaddrinfo(result);
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
    printf("listen failed\n");
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

// allow listener thread to report back its state
MSG msg;
ZeroMemory(&msg, sizeof(MSG));


//force create message queue
PeekMessage(&msg, NULL, WM_USER, WM_USER + 100, PM_NOREMOVE);

printf("Listing for clients on port %s \n", DEFAULT_PORT_STR);
while (listening) {
    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket != INVALID_SOCKET) {
        printf("Client connected\n");

        sender = new SocketSender(ClientSocket);

        listener = new SocketListener(ClientSocket, this->m_threadId);
        printf("Listener created\n");

        listener->setSender(sender);
        listener->startThread();

        printf("Listener started\n");

        listenerList.push_back(listener);
        senderList.push_back(sender);

        printf("Listener list size: %d \n", listenerList.size());

        printf("Listener pushed to list\n");

        //delete socket data if listener close itself due to connection lost or disconnect.

    }
    else {
        int error = WSAGetLastError();
        printf("accept failed\n");
        switch (error) {
        case 10093:
            listening = false;
            try {
                closesocket(ListenSocket);
            }
            catch (...) {}
            return 1;
        }
    }

    printf("Check message queue for thread message\n");
    //check thread message queue
    //GetMessage(&msg, NULL, 0, 0); //this blocks untill a message is get.

    PeekMessage(&msg, NULL, WM_USER, WM_USER + 100, PM_REMOVE);



    if (msg.message == WM_USER + 1)
    {
        //ProcessCustomMessage(msg);
        m_deleteListener((SocketListener*)msg.wParam);
        printf("Recieved message from ThreadID: %d \n", msg.wParam);
    }
    printf("Recieved message from ThreadID: %d \n", msg.message);

    printf("Server socket complete 1 loop\n");
}

return 0;

} }

DWORD SocketListener::m_ThreadFunc() {
listening = true;

rapidxml::xml_document<> doc;

printf("Start thread with ID: %d \n", this->m_threadId);
printf("Parent Thread ID: %d \n", this->_iParentID);


while (listening) {
    int iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0) {
        printf("Bytes received: %d\n", iResult);
        recvbuf[iResult - 1] = 0; // null terminate the string according to the length

        // The message spec indicates the XML will end in a "new line"
        // character which can be either a newline or caraiage feed
        // Search for either and replace with a NULL to terminate
        if (recvbuf[iResult - 2] == '\n' || recvbuf[iResult - 2] == '\r')
            recvbuf[iResult - 2] = 0;

        try { 
            doc.parse<0>(&recvbuf[0]);
            HandleXMLMessage(&doc);
        }

        catch (...) {}

    }
    else {      
        printf("Thread %d is being closed, sending signal to parent (%d)\n", this->m_threadId, this->_iParentID);


        if (PostThreadMessage(this->_iParentID, WM_APP + 1, NULL, NULL) == 0)
        {
            printf("Client cant send Message before closing the conn ! \n");
            printf("Last error %d", GetLastError());
        }
        else {
            printf("Client sent Closing Message successfully \n");
        }


        closesocket(ClientSocket);
        return 1;
    }
}

printf("Server terminate connection\n");

printf("Thread %d is closed, sending signal to parent (%d)\n", this->m_threadId,this->_iParentID);

PostThreadMessage(this->_iParentID, WM_USER + 1, (WPARAM)this->m_threadId, NULL);


return 0;

} }

Thank you very much. 非常感谢你。

accept function is a blocking call, so it looks like after accepting first connection your loop gets stuck at accept函数是一个阻塞调用,所以看起来在接受第一个连接后,您的循环陷入了

ClientSocket = accept(ListenSocket, NULL, NULL);

And does not check thread message queue until the next connection is made. 并且在建立下一个连接之前不会检查线程消息队列。

You also need to check the return result of PeekMessage to know whether message was actually peeked otherwise msg variable will contain garbage. 您还需要检查PeekMessage的返回结果,以了解消息是否实际被窥视了,否则msg变量将包含垃圾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM