Winsock 通过 recv() 接收随机字母
Winsock receiving random letters trough recv()
我正在尝试进行 Winsock 聊天。我想发送位于 2 "tags" 之间的数据包。有点像“^^^TAG^^^ 数据包数据 ^^^TAG^^^”
问题是,我正在使用的客户端应用程序,包括我自己编写的客户端应用程序,要么发送消息错误,要么我的服务器应用程序接收到错误的数据
我的意思是:
Using Hercules TCP Client
Using my own Client
我知道它为什么被拆分,这就是我的标签想法的目的,但是如果您阅读我发送的内容和收到的内容,您会看到添加和替换的字母。在某个时候,我什至收到了我发送的单词,后面跟着“==============================”然后是其他随机 unicode 字符,但我无法再次截图。
由于我从互联网上获得的大多数 TCP 客户端都无法正常工作,我认为问题在于我如何接收数据包,而不是我和其他程序如何发送它们
我的代码:
这是我的代码重写的简单版本
struct client_info
{
SOCKET sock;
const char* ip;
int port;
};
struct server_info
{
SOCKET sock;
const char* ip;
int port;
std::vector<client_info> clients;
int client_count;
HANDLE connection_handler;
HANDLE recv_handler;
};
struct param_info
{
void* server_info_pointer;
};
class my_server
{
public:
my_server(const char* ip, int port)
{
this->m_info.ip = ip;
this->m_info.port = port;
this->start();
this->client_handler();
this->recv_packet();
}
~my_server(void)
{
}
private:
server_info m_info;
bool start(void)
{
WSADATA lpWsaData = decltype(lpWsaData){};
WSAStartup(MAKEWORD(2, 2), &lpWsaData);
this->m_info.sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in lpAddr = decltype(lpAddr){};
lpAddr.sin_family = AF_INET;
lpAddr.sin_addr.S_un.S_addr = inet_addr(this->m_info.ip);
lpAddr.sin_port = htons(this->m_info.port);
char chOption = 1;
setsockopt(this->m_info.sock, SOL_SOCKET, SO_REUSEADDR, &chOption, sizeof(chOption));
setsockopt(this->m_info.sock, IPPROTO_TCP, TCP_NODELAY, &chOption, sizeof(chOption));
if (!bind(this->m_info.sock, reinterpret_cast<sockaddr*>(&lpAddr), sizeof(lpAddr)))
{
return true;
}
closesocket(this->m_info.sock);
WSACleanup();
return false;
}
bool client_handler(void)
{
param_info pi = param_info{};
pi.server_info_pointer = &this->m_info;
if (this->m_info.connection_handler = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
(this->client_handler_internal), &pi, 0, nullptr))
{
return true;
}
return false;
}
static void client_handler_internal(void* param)
{
auto pi = reinterpret_cast<param_info*>(param);
if (!listen(reinterpret_cast<server_info*>(pi->server_info_pointer)->sock, SOMAXCONN))
{
client_info ci = client_info{};
sockaddr_in lpAddr;
int dAddrSize = sizeof(lpAddr);
while (ci.sock = accept(reinterpret_cast<server_info*>(pi->server_info_pointer)->sock, reinterpret_cast<sockaddr*>(&lpAddr), &dAddrSize))
{
ci.ip = inet_ntoa(lpAddr.sin_addr);
ci.port = htons(lpAddr.sin_port);
printf("%s:%d joined!\n", ci.ip, ci.port);
reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.push_back(ci);
memset(&ci, 0, sizeof(ci));
Sleep(100);
}
}
return;
}
auto __forceinline recv_packet(void) -> bool
{
param_info pi = param_info{};
pi.server_info_pointer = &this->m_info;
if (this->m_info.recv_handler = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
(this->recv_packet_internal), &pi, 0, nullptr))
{
return true;
}
return false;
}
static void recv_packet_internal(void* param)
{
auto pi = reinterpret_cast<param_info*>(param);
for (;;)
{
for (int i = 0; i < reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.size(); ++i)
{
char * lpBuffer = new char[64];
if (0 < recv(reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.at(i).sock, lpBuffer, sizeof(lpBuffer), 0))
{
std::string lpNewBuffer = lpBuffer;
printf("%s\n", lpNewBuffer.c_str());
}
memset(lpBuffer, 0, sizeof(lpBuffer));
}
Sleep(50);
}
return;
}
};
if (0 < recv(reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.at(i).sock, lpBuffer, sizeof(lpBuffer), 0))
您忽略了 recv
的 return 值,因此您的代码不知道它收到了多少字节。另外,请参阅下文了解为什么 sizeof(lpBuffer)
在这里是错误的。
memset(lpBuffer, 0, sizeof(lpBuffer));
因为 lpBuffer
是一个 char *
,这会将 sizeof(char *)
字节清零,这是不正确的。仅当您需要 type 的大小时才使用 sizeof
。另外,为什么要将已经使用过并且永远不会再使用的缓冲区归零?
std::string lpNewBuffer = lpBuffer;
您应该在这里使用 recv
中的 return 值来了解 lpNewBuffer
应该是多少字节。
如果不是字符串,请不要将其视为字符串。存储 recv
的 return 值,以便您知道收到了多少字节。
我正在尝试进行 Winsock 聊天。我想发送位于 2 "tags" 之间的数据包。有点像“^^^TAG^^^ 数据包数据 ^^^TAG^^^”
问题是,我正在使用的客户端应用程序,包括我自己编写的客户端应用程序,要么发送消息错误,要么我的服务器应用程序接收到错误的数据
我的意思是:
Using Hercules TCP Client
Using my own Client
我知道它为什么被拆分,这就是我的标签想法的目的,但是如果您阅读我发送的内容和收到的内容,您会看到添加和替换的字母。在某个时候,我什至收到了我发送的单词,后面跟着“==============================”然后是其他随机 unicode 字符,但我无法再次截图。
由于我从互联网上获得的大多数 TCP 客户端都无法正常工作,我认为问题在于我如何接收数据包,而不是我和其他程序如何发送它们
我的代码:
这是我的代码重写的简单版本
struct client_info
{
SOCKET sock;
const char* ip;
int port;
};
struct server_info
{
SOCKET sock;
const char* ip;
int port;
std::vector<client_info> clients;
int client_count;
HANDLE connection_handler;
HANDLE recv_handler;
};
struct param_info
{
void* server_info_pointer;
};
class my_server
{
public:
my_server(const char* ip, int port)
{
this->m_info.ip = ip;
this->m_info.port = port;
this->start();
this->client_handler();
this->recv_packet();
}
~my_server(void)
{
}
private:
server_info m_info;
bool start(void)
{
WSADATA lpWsaData = decltype(lpWsaData){};
WSAStartup(MAKEWORD(2, 2), &lpWsaData);
this->m_info.sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in lpAddr = decltype(lpAddr){};
lpAddr.sin_family = AF_INET;
lpAddr.sin_addr.S_un.S_addr = inet_addr(this->m_info.ip);
lpAddr.sin_port = htons(this->m_info.port);
char chOption = 1;
setsockopt(this->m_info.sock, SOL_SOCKET, SO_REUSEADDR, &chOption, sizeof(chOption));
setsockopt(this->m_info.sock, IPPROTO_TCP, TCP_NODELAY, &chOption, sizeof(chOption));
if (!bind(this->m_info.sock, reinterpret_cast<sockaddr*>(&lpAddr), sizeof(lpAddr)))
{
return true;
}
closesocket(this->m_info.sock);
WSACleanup();
return false;
}
bool client_handler(void)
{
param_info pi = param_info{};
pi.server_info_pointer = &this->m_info;
if (this->m_info.connection_handler = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
(this->client_handler_internal), &pi, 0, nullptr))
{
return true;
}
return false;
}
static void client_handler_internal(void* param)
{
auto pi = reinterpret_cast<param_info*>(param);
if (!listen(reinterpret_cast<server_info*>(pi->server_info_pointer)->sock, SOMAXCONN))
{
client_info ci = client_info{};
sockaddr_in lpAddr;
int dAddrSize = sizeof(lpAddr);
while (ci.sock = accept(reinterpret_cast<server_info*>(pi->server_info_pointer)->sock, reinterpret_cast<sockaddr*>(&lpAddr), &dAddrSize))
{
ci.ip = inet_ntoa(lpAddr.sin_addr);
ci.port = htons(lpAddr.sin_port);
printf("%s:%d joined!\n", ci.ip, ci.port);
reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.push_back(ci);
memset(&ci, 0, sizeof(ci));
Sleep(100);
}
}
return;
}
auto __forceinline recv_packet(void) -> bool
{
param_info pi = param_info{};
pi.server_info_pointer = &this->m_info;
if (this->m_info.recv_handler = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
(this->recv_packet_internal), &pi, 0, nullptr))
{
return true;
}
return false;
}
static void recv_packet_internal(void* param)
{
auto pi = reinterpret_cast<param_info*>(param);
for (;;)
{
for (int i = 0; i < reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.size(); ++i)
{
char * lpBuffer = new char[64];
if (0 < recv(reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.at(i).sock, lpBuffer, sizeof(lpBuffer), 0))
{
std::string lpNewBuffer = lpBuffer;
printf("%s\n", lpNewBuffer.c_str());
}
memset(lpBuffer, 0, sizeof(lpBuffer));
}
Sleep(50);
}
return;
}
};
if (0 < recv(reinterpret_cast<server_info*>(pi->server_info_pointer)->clients.at(i).sock, lpBuffer, sizeof(lpBuffer), 0))
您忽略了 recv
的 return 值,因此您的代码不知道它收到了多少字节。另外,请参阅下文了解为什么 sizeof(lpBuffer)
在这里是错误的。
memset(lpBuffer, 0, sizeof(lpBuffer));
因为 lpBuffer
是一个 char *
,这会将 sizeof(char *)
字节清零,这是不正确的。仅当您需要 type 的大小时才使用 sizeof
。另外,为什么要将已经使用过并且永远不会再使用的缓冲区归零?
std::string lpNewBuffer = lpBuffer;
您应该在这里使用 recv
中的 return 值来了解 lpNewBuffer
应该是多少字节。
如果不是字符串,请不要将其视为字符串。存储 recv
的 return 值,以便您知道收到了多少字节。