C++ TCP 服务器 (Winsock) 连接 (无效客户端) 然后立即关闭

C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes

本文关键字:然后 客户端 连接 TCP 服务器 Winsock C++ 无效      更新时间:2023-10-16

编辑:正在研究解决方案 - 事实证明,谷歌搜索 204.204.204.204 让我比更多的描述性请求更进一步。

真诚地。智慧结束。我不知道我怎么能花一整天的时间做一些在Flask(服务器)和Javascript(客户端)中花了10分钟的事情。我需要它以C++运行,并允许客户端通过同一台机器上的BlueStacks端口进行连接。客户并不重要,因为我甚至无法走那么远。

我尝试过WinSocks,我尝试过WxWidget的网络实现,我什至尝试过一些随机C++包装器的东西。所有这些都失败了(通常在示例中!例如,到处复制粘贴和错误)。所以我最终回到了WinSockets,并在YouTube上学习了一个教程。

int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
return false;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Quitting");
return false;
}
//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
//  wxLogMessage("Client Invalid Socket");
//  return false;
//}
char host[NI_MAXHOST];  //Client's remote name
char service[NI_MAXHOST]; //Service (port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
wxLogMessage(host);
int wut = client.sin_port;
wxString mystring = wxString::Format(wxT("%i"), wut);
wxLogMessage("Connected on port");
wxLogMessage(mystring);
//wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR) {
//wxLogMessage("ERROR in recv");
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
send(clientSocket, buf, bytesReceived + 1, 0);
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
ServerStuff();
//Close(true);
}

在YouTube视频("在C++中创建TCP服务器" - 不允许发布链接)这是有效的!命令窗口打开,无限空白,直到他连接客户端,然后客户端发送消息,服务器回复相同的确切消息作为回报。

不是我的。我的只是匆匆忙忙地完成所有事情,然后关闭。我的日志曾经立即退出注释的代码,其中指出客户端套接字无效,所以我将其注释掉。现在我的输出是: 204.204.204.204 在端口上连接 52428 不知何故走到了这一步

我不知道该怎么办。我只是尝试通过同一台机器的TCP连接发送数据。我很困惑这怎么这么难。似乎某个随机进程立即尝试作为客户端连接到我的服务器?但是,当我在 54000 上显式托管时,为什么允许它在端口 52428 上进行连接?

我的目标: 启动服务器 使用 BlueStacks 中的 Java 应用程序连接到服务器 将数据从服务器发送到客户端

将计算机作为服务器更有意义,因为将有多个BlueStacks实例,我宁愿不必为我正在做的事情"生成"多个程序/服务器。

我在您的套接字代码中看到一些错误。

  • 如果成功,则不调用WSACleanup()WSAStartup()

    然后出现问题。
  • 如果socket()成功,然后出现问题,则不打电话closesocket()

  • 不将您传递给bind()sockaddr_in归零。 结构中的随机字节可能会导致bind()失败。

  • 忽略bind()listen()accept()send()的返回值。

  • 未正确处理getnameinfo()的返回值。 它在成功时返回 0,而不是失败。

  • 向客户端发送比从客户端收到的字节多 +1 个字节。 如果客户端发送的字节数少于缓冲区可以容纳的字节数,则由于调用ZeroMemory(),该额外字节将被0x00。 但是,如果客户端实际上发送了足够的字节来完全填满缓冲区,那么您将从不属于您的内存中发送一个额外的字节。 如果您确实想在回显所有内容之后发送空终止符,请显式执行此操作。 否则,真正的回显服务器应该只发回它收到的确切内容,不多也不少。

尝试更多类似的东西:

void ServerStuff() {
WSADATA WsData;
int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
if (ret != 0) {
wxLogMessage("Can't initialize Winsock! Error: %d", ret);
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
WSACleanup();
return;
}
//Bind the ip and port to a socket
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton
ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Tell winsock the socket is for listening
ret = listen(listening, SOMAXCONN);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Wait for a connection
sockaddr_in client = {};
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
char host[NI_MAXHOST] = {};  //Client's remote name
ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
if (ret != 0) {
wxLogMessage("Can't get client name info! Error: %d", ret);
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
}
wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
int bytesReceived;
while (true)
{
//Wait for client to send data
bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR) {
wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
ret = send(clientSocket, buf, bytesReceived, 0);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
break;
}
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}