I'm trying to create a server client that once its working I can pass a vector into it and send it to a client program through ssh like putty. The issue is whenever I try to connect raw or ssh with putty on 127.0.0.1:45000 the program terminates once it connects.
Here is my code:
#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();
}
I'm writing it and compiling in Visual Studio 2019.
Here's the message I get from Putty when trying to connect with the ssh option or raw.
If anyone can help it would be greatly appreciated. Thanks!
When calling getnameinfo()
, you are return
'ing from main()
immediately, without calling closesocket()
first, regardless of whether getnameinfo()
is successful or fails. This is the root of your Putty error. You are explicitly exiting your app whenever a client connects, without informing the client that the connection is being closed.
More generally, if accept()
is successful (and socket()
, too), you should always call closesocket()
on the returned SOCKET
, regardless of anything else happening in your code (same with WSACleanup()
if WSAStartup()
is successful).
There are several other mistakes in your code:
It is illegal for main()
to have a non-int
return type (though some compilers allow this, as a non-standard extension. Don't rely on this!).
You are missing a return
from main()
if socket()
fails.
You are not checking for errors on bind()
, listen()
, accept()
, or send()
.
There is no point in setting the backlog to SOMAXCONN
if you are only going to accept()
1 client ever.
you have a potential buffer overflow when calling send()
. Imagine if recv()
returned exactly 4096 bytes received. Sending bytesReceived + 1
number of bytes back to the client would go out of bounds of your buf
array.
With that said, try something more like this:
#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;
}