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