App stucks in accept() when LAN interfaces changed - c++

I created a small app on small router with 4 LAN ports. Router has been flashed with OpenWrt system, Linux kernel 5.4.154
Devices connected to LAN ports are sending date over TCP POSTs. The app is listening on specified TCP port and sends data to the server or stores it in SD card. Everything work fine until someone will start playing with plugs on the LAN side. Somethings is happening and app hangs in accept() function waiting for incomming data.
I assume (please correct me if I'm wrong) system changes?/resets? port routing and data are not delivered to the app socket any more.
Is there a simple solution to keep the 'subscription' of TCP port?
I've tried to rewrite app in async mode, but not everything is working correctly, is this the only solution for this problem?
Below simpyfied working(!) code in blocking mode (I removed all unnecesary stuff, so it may not compile)
int main() {
// Create server_socket as socket
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
cerr << "Can't create a socket! Quitting" << endl;
}
int enable = 1;
if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
{
cout << GetTime() << "Can't use SO_REUSEADDR" << endl;
}
while (true) {
// Bind the ip address and port to a socket
listenningport = 55555;
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(listenningport);
inet_pton(AF_INET, "0.0.0.0", &hint.sin_addr);
if (bind(server_socket, (sockaddr*) &hint, sizeof(hint)) == -1) {
cerr << "Can't bind to IP/port" << endl;
}
// Tell Winsock the socket is for server_socket
if (listen(server_socket, SOMAXCONN) == -1) // handle multiconnections SOMAXCONN(4096, queue)
{
cerr << "Can't listen!" << endl;
}
// Wait for a connection
sockaddr_in client;
socklen_t clientSize = sizeof(client);
while (true) {
// Waiting for data on socket; block mode
int clientSocket = accept(server_socket, (sockaddr*) &client, &clientSize);
if (clientSocket == -1) {
cerr << "Problem with client connecting!" << endl;
// break the loop and try to renew socket connection
break;
}
else {
// receive all data till the end of message
int bytesReceived = 0;
while ((bytesReceived = recv(readSocket, out_data + msgSize, maxSizeOutData - msgSize - 1, 0)) > 0) {
msgSize += bytesReceived;
if (msgSize > maxSizeOutData + 1)
break;
}
// no data received
if (bytesReceived == -1) {
cerr << "Error in recv(). BytesReceived = -1" << endl;
}
close(clientSocket);
}
}
}

Related

Error "Invalid padding length on received packet" when connecting to winsock server using PuTTY

I'm mostly new to new to networking so I thought I'd start with something simple so I was trying to make a simple C++ echo server. I'm using PuTTY for testing. When I connect to the server through PuTTY I get a PuTTY error of
Invalid padding length received packet
When I check the server console it says that the PuTTY client connected but disconnected immediatelly.
Here's my code.
#include <stdlib.h>
#include <WS2tcpip.h> //includes the winsock file as well
#include <string>
#pragma comment (lib,"ws2_32.lib")
#define PORT 17027
int main()
{
//Initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &wsData);
if (wsOK != 0)
{
std::cout << "Can't initialize wonsock! Quitting" << std::endl;
return 0;
}
//Create a socket
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET)
{
std::cout << "Can't create socket! Quitting" << std::endl;
return 0;
}
//Bind the socket to an ip address and port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(PORT);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listenSocket, (sockaddr *)&hint, sizeof(hint));
//Tell Winsock the socket is for listening
listen(listenSocket, SOMAXCONN);
//Wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listenSocket, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
std::cout << "Cant accept client! Quitting" << std::endl;
return 0;
}
char host[NI_MAXHOST]; // Client's remote name;
char service[NI_MAXHOST]; // Client's (i.e. 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_MAXHOST, 0) == 0) // try to get name of client
{
std::cout << host << " connected on port " << service << std::endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST); //get address of client
std::cout << host << " connected on port " << ntohs(client.sin_port) << std::endl;
}
//Close listening socket
closesocket(listenSocket);
//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)
{
std::cerr << "Error in recv(). Quitting" << std::endl;
break;
}
if (bytesReceived == 0)
{
std::cerr << "Client disconnected" << std::endl;
break;
}
//Echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
return 0;
}
It looks like you are trying to connect with SSH. Your code is not an SSH server.
To connect to a raw socket server with PuTTY, you need to select the "Raw" connection type.

winsock server send and receive simultaniously

I'm new to WinSock, and I'm trying something out. I have client and server programs that are communicating with each other. If the client types something, the server will just echo it back. I want them to receive and send at the same time, so I put the client in non-blocking mode, and it works kind-of OK. But when I try to put the server in non-blocking, it crashes saying that recv() == SOCKET_ERROR.
So the question is : why can the client work in non-blocking, but the server can't? How can I solve this?
TCP_SERVER:
#include <iostream>
#include <WS2tcpip.h>
#include <Windows.h>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
string receive(SOCKET clientSocket, char* buf)
{
ZeroMemory(buf, 4096);
int bytesReceived = recv(clientSocket, buf, 4096, 0);
string bufStr = buf;
cout << "bytes received: " << bytesReceived << endl;
if (bytesReceived == SOCKET_ERROR)
{
cerr << "error met recv() in de reciev() functie" << endl;
exit(EXIT_FAILURE);
}
if (bytesReceived == 0)
{
cout << "client disconnected" << endl;
exit(EXIT_FAILURE);
}
return bufStr;
}
void main()
{
//initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0) {
cerr << "can't initialize winsock ABORT";
return;
}
//create socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "cant create socket ABORT" << std::endl;
}
//bind IP adress and port to 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 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);
if (clientSocket == INVALID_SOCKET) {
cerr << "somthing went wrong with client socket accept ABORT";
exit(EXIT_FAILURE);
}
char host[NI_MAXHOST]; //client remote name
char service[NI_MAXSERV]; //service (i.e port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)&client, sizeof(client), 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);
//non blocking socket leads to error
u_long mode = 1; // 1 to enable non-blocking socket
ioctlsocket(clientSocket, FIONBIO, &mode);
//non blocking socket
//while loop: accept and echo message to client
char buf[4096];
string inputTxt;
while (true)
{
inputTxt = receive(clientSocket,buf);
send(clientSocket, buf, inputTxt.size() + 1, 0);
}
closesocket(clientSocket);
WSACleanup();
}
TCP_CLIENT:
#include <iostream>
#include <WS2tcpip.h>
#include <Windows.h>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
string receive(SOCKET clientSocket, char* buf)
{
ZeroMemory(buf, 4096);
int bytesReceived = recv(clientSocket, buf, 4096, 0);
string bufStr = buf;
cout << "bytes received: " << bytesReceived << endl;
if (bytesReceived == SOCKET_ERROR)
{
cerr << "error met recv() in de reciev() functie" << endl;
exit(EXIT_FAILURE);
}
if (bytesReceived == 0)
{
cout << "client disconnected" << endl;
exit(EXIT_FAILURE);
}
return bufStr;
}
void main()
{
//initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0) {
cerr << "can't initialize winsock ABORT";
return;
}
//create socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "cant create socket ABORT" << std::endl;
}
//bind IP adress and port to 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 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);
if (clientSocket == INVALID_SOCKET) {
cerr << "somthing went wrong with client socket accept ABORT";
exit(EXIT_FAILURE);
}
char host[NI_MAXHOST]; //client remote name
char service[NI_MAXSERV]; //service (i.e port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)&client, sizeof(client), 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);
/*
//non blocking socket leads to error
u_long mode = 1; // 1 to enable non-blocking socket
ioctlsocket(clientSocket, FIONBIO, &mode);
//non blocking socket
*/
//while loop: accept and echo message to client
char buf[4096];
string inputTxt;
while (true)
{
inputTxt = receive(clientSocket,buf);
send(clientSocket, buf, inputTxt.size() + 1, 0);
}
closesocket(clientSocket);
WSACleanup();
}
You are not handling the case where send()/recv() are failing due to a WSAEWOULDBLOCK error, which is NOT a fatal error. It just means there is no work to be done at that moment, try again later.
For recv(), that means there are no bytes available to read from the socket's receive buffer. The socket will be in a readable state when there are bytes available to read from it, or the peer has performed a graceful disconnect.
For send(), it means the peer's receive buffer is full and can't receive new bytes until the peer reads some bytes to clear up buffer space. Any unsent bytes will have to be passed to send() again at a later time. The socket will be in a writable state when new bytes can be sent to the peer, and not in a writable state when the peer's buffer is full.
When your server accepts a client and tries to receive() from it, recv() is going to keep failing with WSAEWOULDBLOCK until the client actually sends something.
So, you need to handle WSAEWOULDBLOCK properly and retry as needed. Or better, use select() (or WSAAsyncSelect(), or WSAEventSelect(), or Overlapped I/O) to detect the socket's actual state to know when send()/recv() can be safely called without causing an WSAEWOULDBLOCK error.

I coded a c++ server/client program using windows sockets. getting 10061 from wsagetlasterror() trying to connect using my public ip addr

Im attempting to connect to my server via my client and if i use my local host address 127.0.0.1 everything works perfectly fine. it connects and im able to send data. however whenever i switch it to my public address it fails to connect. i already went through my router and forwarded the port im using. and ive tested if the port is open with canyouseeme.org and port forward network utilities. the error code i get from getlasterror() is 10061. i also called my isp and they told me the port is open so i should be able to connect but im not. i turned off my firewall and AV as well. i have windows 10 64 bit. im at a loss and would really appreciate the help. the error code means that the server is actively refusing the connection. but nothing happens on my server side...it stays in the accept() call.
this is the server code. how do i solve this issue? i currently have both the server and client on one computer.
class Server
{
public:
Server(int port)
:
port(port)
{
std::cout << "Initializing server...\n";
if (WSAStartup(version, &wsData) == 0)
{
auto result = createListenSock();
//if no value is returned, it was a success
if (!result.has_value())
std::cout << "Successfully created a server! Accepting Clients now.\n";
else
std::cout << result.value() << std::endl;
}
else
std::cout << "Failed to initialize WinSock. Error : " << WSAGetLastError() << std::endl;
}
~Server()
{
closesocket(listensock);
closesocket(client);
WSACleanup();
}
std::optional<std::string> acceptClient()
{
int sz = sizeof(clientinfo);
if ((client = accept(listensock, (sockaddr*)&clientinfo, &sz)) == INVALID_SOCKET)
return {};
else
{
char clientipaddr[100];
inet_ntop(AF_INET, &clientinfo.sin_addr, clientipaddr, sizeof(clientipaddr));
return std::string(clientipaddr);
}
}
private:
std::optional<std::string> createListenSock()
{
//AF_INET for ipv4
//SOCK_STREAM A socket type that provides sequenced, reliable, two-way,
//connection-based byte streams with an OOB data transmission mechanism.
if ((listensock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return "Failed to created listen socket...\n";
initConnectionInfo();
if (bind(listensock, (sockaddr*)&serverInfo, sizeof(serverInfo)) == SOCKET_ERROR)
return "Failed to bind...\n";
if (listen(listensock, SOMAXCONN) == SOCKET_ERROR)
return "Failed to put into listening mode...\n";
//if it returns an empty container, that means it was successful
return {};
}
void initConnectionInfo()
{
//make it use ipv4
serverInfo.sin_family = AF_INET;
//htons converts the port from host to network byte order.
serverInfo.sin_port = htons(port);
//specify that we can accept any ip address
serverInfo.sin_addr.S_un.S_addr = INADDR_ANY;
}
private:
WSADATA wsData;
int version = MAKEWORD(2,2);
SOCKET listensock;
sockaddr_in serverInfo;
int port;
private:
//client variables
SOCKET client;
sockaddr_in clientinfo;
};
int main()
{
//create server
Server server(1024);
auto clientip = server.acceptClient();
if (!clientip.has_value())
{
std::cout << "Couldn't connect to client.";
system("pause");
return 0;
}
std::cout << "Connected to client!" << std::endl << "Client IP Address: " << clientip.value() << std::endl;
and this is the client code
SOCKET startclient()
{
WSADATA data;
//server to connect to
std::string ipAddress = "127.0.0.1"; //IF I CHANGE THIS TO MY PUBLIC IP ADDRESS IT FAILS TO CONNECT
int port = 1024;
// initialize winsock
if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
{
std::cout << "Could not initialize WinSock...\n";
return SOCKET_ERROR;
}
//create a socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
std::cout << "Couldn't create a socket, Error " << WSAGetLastError() << std::endl;
WSACleanup();
return SOCKET_ERROR;
}
//this tells our socket what info to use to connect to the server
sockaddr_in serverinfo;
serverinfo.sin_family = AF_INET;
//htons converts the port number from host to network byte order
serverinfo.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &serverinfo.sin_addr);
std::cout << "Attempting to connect..." << std::endl;
if (connect(sock, (sockaddr*)&serverinfo, sizeof(serverinfo)) == SOCKET_ERROR)
{
std::cout << "Failed to connect... Error : " << WSAGetLastError() << std::endl;
WSACleanup();
closesocket(sock);
return SOCKET_ERROR;
}
else
std::cout << "Connected!" << std::endl;
return sock;
}
int main()
{
SOCKET client = startclient();
if (client == SOCKET_ERROR)
{
system("pause");
return 0;
}

TCP Server Socket Opening Fail in C++

I am currently creating a program where I require a TCP server for communication with an android application. I have written and tested the TCP server as an individual project and it runs completely fine. When including this into a larger project, where I have other processes, it no longer opens the socket for listening.
My project is being created in Visual Studio 2017 and the libraries I am using are:
WS2_32.lib for the TCP
OpenCV for image processing
Libcurl for sending files to a database
ACTi SDK for pulling image feed from a camera
The TCP server code I have written is (taken from https://www.youtube.com/watch?v=WDn-htpBlnU&t=162s):
void TCPServer()
{
//Initalize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't init winsock" << endl;
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create socket" << endl;
return;
}
//Bind the socket to an ip address and port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(100);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could 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);
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; //Service the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), 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);
//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()" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client disconnected" << endl;
break;
}
cout << buf << endl;
}
//Close the socket
closesocket(clientsocket);
//cleanup windsock
WSACleanup();
}
As I said, this code works as an individual project however, when I include this into my overall project the socket fails to open and a connection to 204.204.204.204 is instantly made. This was checked in both situations by viewing all open sockets with netstat. I feel this may be a library conflict, maybe between WS2_32 and libcurl, however I am unsure.
I am currently testing this by calling TCPServer() in my main, however I plan to run the server threaded along with my other processes.
Any suggestions as to why the socket may be failing to open would be much appreciated.
After carrying out checks on the function it was possible to narrow the failure down to the bind(...) function. It seems the error is down to having using namespace std;
The solution was to call bind from the global namespace by doing ::bind(...). This solution was found here: Compilation errors with socket bind function

C++ Socket Connection automatically establishing?

I am currently programming a C++ module that creates a socket server thread, which polls the accept() function every 1ms. I have a test module that spoofs a client connection that is also running. The test module initiates the creation of the server thread. After the thread is created and verified to be running, the client runs the connect() command as a test. My code states that a connection was established, returning a 0 on the connect command. However, the accept() running in my server thread never receives the connection.
The server is bound to accepting any IP:50000, and the client is not bound, but has 127.0.0.1:50000 set as its destination. Is my Linux environment automatically accepting this connection?
Here is the code for my server's socket:
int nSocket;
int nOn = 1;
int nControl;
struct sockaddr_in sServerAddress;
nSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(nSocket < 0)
{
std::cout << "Failed to create socket\n";
}
if(setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, &nOn, sizeof(int)) < 0)
{
std::cout << "failed to set socket option\n";
}
nControl = fcntl(nSocket, F_GETFL);
if(fcntl(nSocket, F_SETFL, O_NONBLOCK | nControl) < 0)
{
std::cout << "set not blocking failed\n";
}
memset(&sServerAddress, 0x00, sizeof(struct sockaddr_in));
sServerAddress.sin_family = AF_INET;
sServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
sServerAddress.sin_port = htons(mtListenPort);
if(bind(nSocket, (struct sockaddr*)&sServerAddress, sizeof(struct sockaddr_in)) < 0)
{
std::cout << errno << "bind failed\n";
}
if(listen(nSocket, MAXPENDING) < 0)
{
std::cout << "listen failed\n";
}
Here is the code for my test client's socket:
int nSocket;
nSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(nSocket < 0)
{
std::cout << "Failed to create socket\n";
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
inet_aton(LOCAL_HOST, &serverAddress.sin_addr);
serverAddress.sin_port = htons(LISTEN_PORT00);
char msg[] = "Hello World.";
usleep(10000);
if (connect(nSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
std::cout << errno << "Could not connect to the server.\n";
}
usleep(10000);
if (sendto(nSocket, msg, strlen(msg), 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
std::cout << errno << "Could not send data to the server.\n";
}
Here is a small part of the thread that runs the accept code.
while(mbListening)
{
nMessengerSocket = accept(mnSocket, (struct sockaddr*)&sClientAddr, &tClientAddrLength);
if(nMessengerSocket >= 0)
{
std::cout << "Accepted connection from " << inet_ntoa(sClientAddr.sin_addr) << std::endl;
mnConnections++;
mbListening = false;
}
mThreadRunningTime++;
usleep(1000);
}
Make sure tClientAddrLength is initialized to sizeof sClientAddr before calling accept(). That is a common error.
Don't silently ignore errors. Examine the error code in errno because it tells you what went wrong.
Are you using sendto? That's for UDP... Use send.
Also, check if the port is free:
telnet localhost 50000
netstat -a