与 127.0.0.1 上的 Putty 客户端连接时 C++ Winsock 库终止
C++ Winsock Library Termination When connecting with Putty Client on 127.0.0.1
我正在尝试创建一个服务器客户端,一旦它工作,我就可以将一个向量传递给它,并通过 ssh 将其发送到一个客户端程序,就像 putty 一样。问题是每当我尝试在 127.0.0.1:45000 上使用 putty 连接 raw 或 ssh 时,程序在连接后终止。
这是我的代码:
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
// Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Intitialze winsock! Quiting" << endl;
return;
}
// Create a socket to bind
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
}
// Bind the socket to an ip address to the port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(45000);
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 connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; // Service (port) the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST); // use mem set of linux
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
return;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
return;
}
// Close listening socket
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)
{
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client Disconnected, bytes 0" << endl;
break;
}
// echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
// Close the socket
}
closesocket(clientSocket);
// Shutdown winsock
WSACleanup();
}
我正在 Visual Studio 2019 年编写和编译。
这是我在尝试使用 ssh 选项或原始连接时从 Putty 收到的消息。
如果有人能提供帮助,我们将不胜感激。谢谢!
调用 getnameinfo()
时,您会立即从 main()
return
'ing,而无需先调用 closesocket()
,无论 getnameinfo()
是否成功或失败。这是您的 Putty 错误的根源。每当客户端连接时,您都会明确退出您的应用程序,而不通知客户端连接正在关闭。
更一般地说,如果 accept()
成功(并且 socket()
也成功),您应该 始终 在 returned SOCKET
,无论您的代码中发生了什么(与 WSACleanup()
相同,如果 WSAStartup()
成功)。
您的代码中还有其他几个错误:
非法 main()
具有非int
return 类型(尽管 一些编译器允许这个,作为一个非标准的扩展。不要依赖这个!)。
如果 socket()
失败,您缺少来自 main()
的 return
。
您没有检查 bind()
、listen()
、accept()
或 send()
.
上的错误
如果您只去 accept()
1 个客户,那么将积压设置为 SOMAXCONN
毫无意义。
您在调用 send()
时可能会发生缓冲区溢出。想象一下,如果 recv()
returned 正好 收到 4096 个字节。将 bytesReceived + 1
字节数发送回客户端会超出 buf
数组的范围。
话虽如此,试试这样的东西:
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
int main()
{
// Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int errCode = WSAStartup(ver, &wsData);
if (errCode != 0)
{
cerr << "Can't initialize winsock! Error " << errCode << ". Quitting" << endl;
return 0;
}
// Create a socket to bind
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
errCode = WSAGetLastError();
cerr << "Can't create listening socket! Error " << errCode << ". Quitting" << endl;
WSACleanup();
return 0;
}
// Bind the socket to an ip address to the port
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(45000);
hint.sin_addr.s_addr = INADDR_ANY; // could also use inet_pton
if (bind(listening, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Can't bind listening socket! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
// Tell winsock the socket is for listening
if (listen(listening, 1) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Can't open listening socket! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
// Wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
errCode = WSAGetLastError();
cerr << "Can't accept a client! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; // Service (port) the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST); // use mem set of linux
if (getnameinfo((sockaddr*)&client, clientSize, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}
// Close listening socket
closesocket(listening);
listening = INVALID_SOCKET;
// while loop; accept and echo message back to client
char buf[4096];
while (true)
{
// wait for client to send data
int bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Error reading from client: " << errCode << ". Quitting" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client Disconnected" << endl;
break;
}
// echo message back to client
char *ptr = buf;
int bytesToSend = bytesReceived;
do
{
int bytesSent = send(clientSocket, ptr, bytesToSend, 0);
if (bytesSent == SOCKET_ERROR)
break;
ptr += bytesSent;
bytesToSend -= bytesSent;
}
while (bytesToSend > 0);
if (bytesToSend != 0)
{
errCode = WSAGetLastError();
cerr << "Error writing to client: " << errCode << ". Quitting" << endl;
break;
}
}
// Close the client socket
closesocket(clientSocket);
// Shutdown winsock
WSACleanup();
return 0;
}
我正在尝试创建一个服务器客户端,一旦它工作,我就可以将一个向量传递给它,并通过 ssh 将其发送到一个客户端程序,就像 putty 一样。问题是每当我尝试在 127.0.0.1:45000 上使用 putty 连接 raw 或 ssh 时,程序在连接后终止。
这是我的代码:
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
// Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Intitialze winsock! Quiting" << endl;
return;
}
// Create a socket to bind
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
}
// Bind the socket to an ip address to the port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(45000);
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 connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; // Service (port) the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST); // use mem set of linux
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
return;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
return;
}
// Close listening socket
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)
{
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client Disconnected, bytes 0" << endl;
break;
}
// echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
// Close the socket
}
closesocket(clientSocket);
// Shutdown winsock
WSACleanup();
}
我正在 Visual Studio 2019 年编写和编译。
这是我在尝试使用 ssh 选项或原始连接时从 Putty 收到的消息。
如果有人能提供帮助,我们将不胜感激。谢谢!
调用 getnameinfo()
时,您会立即从 main()
return
'ing,而无需先调用 closesocket()
,无论 getnameinfo()
是否成功或失败。这是您的 Putty 错误的根源。每当客户端连接时,您都会明确退出您的应用程序,而不通知客户端连接正在关闭。
更一般地说,如果 accept()
成功(并且 socket()
也成功),您应该 始终 在 returned SOCKET
,无论您的代码中发生了什么(与 WSACleanup()
相同,如果 WSAStartup()
成功)。
您的代码中还有其他几个错误:
非法
main()
具有非int
return 类型(尽管 一些编译器允许这个,作为一个非标准的扩展。不要依赖这个!)。如果
socket()
失败,您缺少来自main()
的return
。您没有检查
上的错误bind()
、listen()
、accept()
或send()
.如果您只去
accept()
1 个客户,那么将积压设置为SOMAXCONN
毫无意义。您在调用
send()
时可能会发生缓冲区溢出。想象一下,如果recv()
returned 正好 收到 4096 个字节。将bytesReceived + 1
字节数发送回客户端会超出buf
数组的范围。
话虽如此,试试这样的东西:
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
int main()
{
// Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int errCode = WSAStartup(ver, &wsData);
if (errCode != 0)
{
cerr << "Can't initialize winsock! Error " << errCode << ". Quitting" << endl;
return 0;
}
// Create a socket to bind
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
errCode = WSAGetLastError();
cerr << "Can't create listening socket! Error " << errCode << ". Quitting" << endl;
WSACleanup();
return 0;
}
// Bind the socket to an ip address to the port
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(45000);
hint.sin_addr.s_addr = INADDR_ANY; // could also use inet_pton
if (bind(listening, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Can't bind listening socket! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
// Tell winsock the socket is for listening
if (listen(listening, 1) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Can't open listening socket! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
// Wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
errCode = WSAGetLastError();
cerr << "Can't accept a client! Error " << errCode << ". Quitting" << endl;
closesocket(listening);
WSACleanup();
return 0;
}
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; // Service (port) the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST); // use mem set of linux
if (getnameinfo((sockaddr*)&client, clientSize, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}
// Close listening socket
closesocket(listening);
listening = INVALID_SOCKET;
// while loop; accept and echo message back to client
char buf[4096];
while (true)
{
// wait for client to send data
int bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR)
{
errCode = WSAGetLastError();
cerr << "Error reading from client: " << errCode << ". Quitting" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client Disconnected" << endl;
break;
}
// echo message back to client
char *ptr = buf;
int bytesToSend = bytesReceived;
do
{
int bytesSent = send(clientSocket, ptr, bytesToSend, 0);
if (bytesSent == SOCKET_ERROR)
break;
ptr += bytesSent;
bytesToSend -= bytesSent;
}
while (bytesToSend > 0);
if (bytesToSend != 0)
{
errCode = WSAGetLastError();
cerr << "Error writing to client: " << errCode << ". Quitting" << endl;
break;
}
}
// Close the client socket
closesocket(clientSocket);
// Shutdown winsock
WSACleanup();
return 0;
}