C ++ TCP服务器(Winsock)立即连接(无效客户端)然后关闭
C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes
编辑:研究解决方案 - 谷歌搜索 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 视频上("Creating a TCP Server in C++" - 不允许 post 链接)这有效!命令 window 打开,无限空白,直到他连接到客户端,然后客户端发送一条消息,服务器在 return.
中回复完全相同的消息
不是我的。我的只是冲过一切然后关闭。我的日志过去常常立即退出注释代码,其中指出客户端套接字无效,所以我将其注释掉。现在我的输出是:
204.204.204.204
已连接端口
52428
不知何故走到这一步
我不知道该怎么办。我只是想通过同一台机器的 TCP 连接发送数据。我很困惑这怎么这么难。似乎一些随机进程正在立即尝试作为客户端连接到我的服务器?但是,当我明确托管在 54000 上时,为什么它允许连接到端口 52428?
我的目标:
启动服务器
使用 BlueStacks 中的 Java 应用程序连接到服务器
从服务器向客户端发送数据
将计算机作为服务器更有意义,因为会有多个 BlueStacks 实例,我宁愿不必 "spawn" 多个程序/服务器来完成我正在做的事情。
我看到你的套接字代码中有一些错误。
如果 WSAStartup()
成功,则不调用 WSACleanup()
,然后出现问题。
如果 socket()
成功,则不调用 closesocket()
,然后出现问题。
没有将您传递给 bind()
的 sockaddr_in
清零。结构中的随机字节可能导致 bind()
失败。
忽略 bind()
、listen()
、accept()
和 send()
的 return 值。
没有正确处理 getnameinfo()
的 return 值。 return成功时为 0,失败时为 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");
}
编辑:研究解决方案 - 谷歌搜索 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 视频上("Creating a TCP Server in C++" - 不允许 post 链接)这有效!命令 window 打开,无限空白,直到他连接到客户端,然后客户端发送一条消息,服务器在 return.
中回复完全相同的消息不是我的。我的只是冲过一切然后关闭。我的日志过去常常立即退出注释代码,其中指出客户端套接字无效,所以我将其注释掉。现在我的输出是: 204.204.204.204 已连接端口 52428 不知何故走到这一步
我不知道该怎么办。我只是想通过同一台机器的 TCP 连接发送数据。我很困惑这怎么这么难。似乎一些随机进程正在立即尝试作为客户端连接到我的服务器?但是,当我明确托管在 54000 上时,为什么它允许连接到端口 52428?
我的目标: 启动服务器 使用 BlueStacks 中的 Java 应用程序连接到服务器 从服务器向客户端发送数据
将计算机作为服务器更有意义,因为会有多个 BlueStacks 实例,我宁愿不必 "spawn" 多个程序/服务器来完成我正在做的事情。
我看到你的套接字代码中有一些错误。
如果
WSAStartup()
成功,则不调用WSACleanup()
,然后出现问题。如果
socket()
成功,则不调用closesocket()
,然后出现问题。没有将您传递给
bind()
的sockaddr_in
清零。结构中的随机字节可能导致bind()
失败。忽略
bind()
、listen()
、accept()
和send()
的 return 值。没有正确处理
getnameinfo()
的 return 值。 return成功时为 0,失败时为 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");
}