1

我想在 Qt 或 C++ 中为 TCP 中的 recv() 函数创建一个类似的插槽,这样当套接字接收到数据时它会自动调用插槽,我可以使用 QTcpSockets 来完成,但我不能使用它们由于一些限制。目前我正在使用计时器从 recv() 函数接收数据。

请指导我正确的方向。

tcp.h

    ifndef TCP_H
    #define TCP_H

    #pragma once
    #include <WinSock2.h>
    #include <WS2tcpip.h>
    #include <iostream>
    #include "config.h"
    #include "tcp_packets.h"
    #include "change_ending.h"
    #include "md5.h"
    #pragma comment(lib, "Ws2_32.lib")

    class CTcpClient
    {
    private:
    char* szServerName;
    char*   Port;
    SOCKET ConnectSocket;
    md5checksum Md5Var;

    public:
        int Size;
        bool Send(char* szMsg,int len);
        CTcpClient(char* servername,char* port)
        {
            Port=port;
            szServerName = servername;
            ConnectSocket = INVALID_SOCKET;
            Size=0;


        }

        bool Start();
        void Stop();
        // Free the resouces




        // Receive message from server
         char recvbuf[DEFAULT_BUFFER_PKT_LENGTH];
        void Recv();


    };

tcp.cpp

    #endif // TCP_H
tcp.cpp
#include "tcp.h"
#include "config.h"

bool CTcpClient::Start() {
        WSADATA wsaData;

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

        struct addrinfo *result = NULL,
                        *ptr = NULL,
                        hints;

        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        //hints.ai_protocol = SOL_SOCKET;
        //Resolve the server address and port
        iResult = getaddrinfo(szServerName,Port, &hints, &result);
        if (iResult != 0)
        {
            printf("getaddrinfo failed: %d\n", iResult);
            WSACleanup();
            return false;
        }

        ptr = result;

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);


        if (ConnectSocket == INVALID_SOCKET)
        {
            printf("Error at socket(): %d\n", WSAGetLastError());
            freeaddrinfo(result);
            WSACleanup();
            return false;
        }

        // Connect to server
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);

        if (iResult == SOCKET_ERROR)
        {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
        }

        freeaddrinfo(result);

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

        return true;
    }
void CTcpClient::Stop() {
        int iResult = shutdown(ConnectSocket, SD_SEND);

        if (iResult == SOCKET_ERROR)
        {
            printf("shutdown failed: %d\n", WSAGetLastError());
        }

        closesocket(ConnectSocket);
        WSACleanup();
    }
bool CTcpClient::Send(char* szMsg,int len)
    {

        int iResult = send(ConnectSocket, szMsg, len, 0);

        if (iResult == SOCKET_ERROR)
        {
            printf("send failed: %d\n", WSAGetLastError());
            Stop();
            return false;
        }

        return true;
    }
void CTcpClient::Recv()
    {



        int iResult = recv(ConnectSocket, recvbuf, DEFAULT_REC_BUFFER_PKT_LENGTH, 0);
        Size=iResult;
        if (iResult > 0)
        {
            char msg[DEFAULT_REC_BUFFER_PKT_LENGTH];
            memset(&msg, 0, sizeof(msg));
            strncpy(msg, recvbuf, iResult);

            printf("Received: %s\n", msg);


        }


        //return false;
    }
4

1 回答 1

1

如果可以,您可以为 Recv() 函数创建单独的线程并将其回调函数作为参数。然后在每次从套接字获取数据时在单独的线程中调用回调函数。

void callback(char *data){
     printf("Received: %s\r\n", data);
}
void* thread_function(void *input){
     void (*callb)(char*) = (void (*)(char*))input;
     int recieve;
     while(1){
          receive = recv();
          if(receive > 0)
               callb();
     }
return NULL;
}
int main(){
pthread_t thread;
pthread_create(thread, NULL, thread_function, &callback);
/* do some stuff */
pthread_join(thread);
return 0;
}

像这样的东西。缺少很多变量和参数,但它显示了主要思想。

于 2013-09-17T14:16:06.290 回答