c++ recv()持续返回-1

q0qdq0h2  于 2023-01-03  发布在  其他
关注(0)|答案(1)|浏览(344)

我正在客户端和服务器之间创建一个服务器代理。目前我已经在python中找到了这个想法的基础,我正在尝试将其转换为C++。然而,我的代码似乎无法正常工作,我感到很困难。
显然recv一直返回SOCKET_ERROR,所以我想也许我在winsock上做错了什么。

#include <iostream>
#include <string>
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <vector>
#include <sstream>
#pragma comment(lib, "Ws2_32.lib")

void parse(char* data, int len, int port, const std::string& origin) {
    std::cout << "[" << origin << "(" << port << ")] " << data << std::endl;
}

struct ProxyToServer {
    SOCKET m_client;
    SOCKET m_server;
    int m_port;

    ProxyToServer() = default;

    ProxyToServer(const char* host, int port) {
        m_port = port;
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) {
                sockaddr_in server_addr;
                server_addr.sin_family = AF_INET;
                server_addr.sin_port = htons(port);
                inet_pton(AF_INET, host, &server_addr.sin_addr);
                if ((m_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
                    std::cerr << "[Proxy2Server] Could not create socket!\n";
                }
                if (connect(m_server, reinterpret_cast<sockaddr*>(&server_addr), sizeof(server_addr)) != 0) {
                    std::cerr << "[Proxy2Server] Could not connect socket!\n";
                }
            if (WSACleanup() != 0) {
                std::cerr << "Cleanup failed!\n";
            }
        }
        else {
            std::cerr << " Winsock startup failed!\n";
        }
    }

    void execute() {
        char data[4096];
        while (true) {
            int totalRecv = recv(m_server, data, 4096, 0);
            if (totalRecv == SOCKET_ERROR) std::cout << "Socket error... (recv)" << std::endl;
            if (totalRecv > 0) {
                parse(data, 4096, m_port, "server");
                send(m_client, data, totalRecv, 0);
            }
        }
    }
};

struct ClientToProxy {
    SOCKET m_server;
    SOCKET m_client;
    int m_port;

    ClientToProxy() = default;

    ClientToProxy(const char* host, int port) {
        m_port = port;
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) {
            if (LOBYTE(wsaData.wVersion) >= 2) {
                SOCKET sock;
                if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
                    std::cerr << "[Client2Proxy] Could not create socket!\n";
                }
                const int enable = 1;
                setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*) & enable, sizeof(enable));

                sockaddr_in sock_addr;
                sock_addr.sin_family = AF_INET;
                sock_addr.sin_port = htons(port);
                inet_pton(AF_INET, host, &sock_addr.sin_addr);
                if (bind(sock, (sockaddr*)&sock_addr, sizeof(sock_addr)) != 0) {
                    std::cerr << "[Client2Proxy] Could not bind socket!\n";
                }
                if (listen(sock, 100) != 0) {
                    std::cerr << "[Client2Proxy] Could not listen!\n";
                }
                sockaddr_in clientSockAddr;
                int clientSockSize = sizeof(clientSockAddr);
                m_client = accept(sock,reinterpret_cast<sockaddr*>(&clientSockAddr),&clientSockSize);
                if (m_client == INVALID_SOCKET) std::cerr << "Invalid Client! " << std::endl;
            }
            else {
                std::cerr << "Requested winsock ver is not supported! \n";
            }
            if (WSACleanup() != 0) {
                std::cerr << "Cleanup failed!\n";
            }
        }
        else {
            std::cerr << " Winsock startup failed!\n";
        }
    }

    void execute() {
        while (true) {
            char data[4096];
            int totalRecv = recv(m_client, data, sizeof(data), 0);
            if (totalRecv == SOCKET_ERROR) std::cout << "Socket error... (recv) " << std::endl;
            if (totalRecv > 0) {
                parse(data, 4096, m_port, "client");
                send(m_server, data, sizeof(data), 0);
            }
        }
    }
};

struct Proxy {
    const char* m_from_host;
    const char* m_to_host;
    int m_port;
    ClientToProxy g2p;
    ProxyToServer p2s;

    Proxy(const char* from_host, const char* to_host, int port) : m_from_host(from_host), m_to_host(to_host), m_port(port) {}

    void execute() {
        while (true) {
            std::cout << "[proxy(" << m_port << ")] setting up" << std::endl;
            g2p = ClientToProxy(m_from_host, m_port);
            p2s = ProxyToServer(m_to_host, m_port);
            std::cout << "[proxy(" << m_port << ")] connection established" << std::endl;
            p2s.m_client = g2p.m_client;
            g2p.m_server = p2s.m_server;
            std::thread t1(&ClientToProxy::execute, &g2p);
            std::thread t2(&ProxyToServer::execute, &p2s);
            t1.join();
            t2.join();
        }
    }
};

int main() {
    Proxy master_server("127.0.0.1", "183.211.202.94", 13011);
    std::thread t3(&Proxy::execute, &master_server);
    t3.join();

    /*
    std::vector<Proxy> game_servers;
    for (int port = 13000; port < 13006; port++) {
        Proxy game_server("127.0.0.1", "185.212.200.90", port);
        std::thread t4(&Proxy::execute, &game_server);
        game_servers.push_back(game_server);
        t4.join();
    }*/
}

不幸的是我不知道如何减少这段代码。问题出现在两个类中的所有recv调用中。
注B我非常肯定,所有的IP是正确的,以及端口。

kpbwa7wx

kpbwa7wx1#

recv()似乎返回了SOCKET_ERROR,这是一个定义为(-1)的宏。当recv()执行期间出错时,将返回此值。
要解决此问题,可以尝试以下操作:
1.在recv()函数之后立即调用WSAGetLastError()以获取错误代码。然后,您可以在Windows套接字错误代码文档中查找错误代码,以了解错误的含义。
1.在调用recv()之前,请确保套接字已正确连接。您可以通过使用SO_ERROR选项调用getsockopt()函数来检查连接状态。
1.确保服务器确实在向客户端发送数据,如果服务器没有发送任何数据,recv()将返回0。
1.请确保用于接收数据的缓冲区足够大,可以容纳服务器发送的数据。如果缓冲区太小,recv()可能无法接收所有数据,这可能导致返回SOCKET_ERROR

相关问题