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);
}
}
}
I have a strange problem: I have written a c++ programm which is supposed to connect to ip enabled scales. It is using standard c++ sockets.
When I run the programm against real device (address 192.168.30.200 port 23) i am getting errno=ECONNREFUSED (connection refused).
When I run the same program against my dummy server created in python - it is working like a charm (I am using "server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)" etc.
When I connect to the scale from bash with a command "echo "FB_INFO" | netcat -w 3 192.168.30.200 23" (the same address and port) - the scale replies with correct answer. So it is NOT refusing connections.
I have no clue even how to try to debug where is the problem.
Here is my code:
#define PORT 60000
#define ADDRESS "10.0.10.100"
int scale_port=PORT; // scale port number
string scale_ip = ADDRESS; // scale IP address
// connect to scale, and process commands in a loop.
// upon succesfull processing of every complete set of commands
// execute given OS script/shell/command [NOT IMPLEMENTED]
int daemon_connection(int sock, struct sockaddr_in serv_addr)
{
int valread=0;
int connectstatus=connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if (connectstatus<0)
//if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
cout << "DAEMON:Error - socket connection failed status "<< connectstatus;
cout << " errno=" << errno << endl;
socketErrPrint(errno);
return -1;
}
cout << "DAEMON: connected to socket" << sock << endl;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
(...)
}
// the main loop: create socket, parse address and call connect to scale
// and retry forever if connection broken or unsuccesfull
int daemon(string addr, int port)
{
int sock = 0;
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
cout << "DAEMON: Socket creation error" << endl;
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, addr.c_str(), &serv_addr.sin_addr) <= 0)
{
cout << "DAEMON: error - invalid address "<< addr << " or address not supported" << endl;
return -1;
}
int result=daemon_connection(sock,serv_addr);
}
(...)
I'm currently working on a simple server/client application using C++ in Visual Studio to send a message from one computer to another via an Ethernet/LAN cable connection. I am using code for both client and server that I found online.
When I run the programs on the same computer, I can receive messages from the server. However, if I run the client program on one computer and run the server program on another computer, I do not receive any messages.
Since I am just using an Ethernet cable to communicate between two computers, I set the IP addresses (from Local Network Sharing, Adapter settings, TCP/IPv4) to be specific for both computers, such that the server computer is 10.0.1.2 and the client computer is 10.0.1.1, both with a subnet mask of 255.255.255.0. And then, in the code, I use addr.sin_addr.s_addr = inet_addr("10.0.1.2") for server and addr.sin_addr.s_addr = inet_addr("10.0.1.1") for client accordingly.
But I am still having the problem of sending messages from one computer to another.
Here is the code:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
SOCKADDR_IN addr; //Address to be binded to our Connection socket
int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
addr.sin_addr.s_addr = inet_addr("10.0.1.1");
addr.sin_port = htons(139); //Port = 139
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Set Connection socket
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char MOTD[256];
while (1)
{
recv(Connection, MOTD, sizeof(MOTD), NULL); //Receive Message of the Day buffer into MOTD array
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
Sleep(500);
}
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//WinSock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SOCKADDR_IN addr; //Address that we will bind our listening socket to
int addrlen = sizeof(addr); //length of the address (required for accept call)
addr.sin_addr.s_addr = inet_addr("10.0.1.2");
addr.sin_port = htons(139); //Port
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections
int counter = 0;
SOCKET newConnection; //Socket to hold the client's connection
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == 0) //If accepting the client connection failed
{
std::cout << "Failed to accept the client's connection." << std::endl;
}
else //If client connection properly accepted
{
std::cout << "Client Connected!" << std::endl;
while (counter <100)
{
char MD[256] = "Hi there."; //Create buffer with message
send(newConnection, MD, sizeof(MD), NULL); //Send MD buffer
counter++;
}
}
system("pause");
return 0;
}
I really don't know what to do now. I can ping from one computer to another, but I can not make it work to send a message from one computer to another via the Ethernet connection.
The main problem is that the client is connecting to the wrong IP. The server's IP is 10.0.1.2, but the client is trying to connect to 10.0.1.1 instead. That is why it doesn't work across multiple computers. The client needs to connect to the server's IP, not the client's IP.
Also, you are making several other mistakes in general.
On the server side, you are ignoring the return values of bind() and listen(), and accept() returns INVALID_SOCKET (-1) on error instead of 0.
On the client side, you are ignoring the return value of recv(). It returns -1 on error, 0 on graceful disconnect, and > 0 for the number of bytes actually read. You need to pay attention to that, especially when you are sending the read data to std::cout. You are passing a char[] to operator<<, so the data must be null-terminated, but recv() does not do guarantee that. So, either:
add a null terminator to the end of the char[] data after reading it:
int numRead = recv(Connection, MOTD, sizeof(MOTD)-1, NULL);
if (numRead <= 0) break;
MOTD[numRead] = 0; // <-- here
std::cout << "MOTD:" << MOTD << std::endl;
pass the char[] to std::cin.write() instead of operator<<, specifying the actual number of bytes read in the count parameter:
int numRead = recv(Connection, MOTD, sizeof(MOTD), NULL);
if (numRead <= 0) break;
std::cout << "MOTD:";
std::cout.write(MOTD, numRead); // <-- here
std::cout << std::endl;
And your MOTD protocol is not very well designed in general. The server is sending 256 bytes (if you are lucky, send() can send fewer bytes!) for every message, even though only 9 bytes are actually being used. So you are wasting bandwidth. The client is expecting to receive exactly 256 bytes every time (which is not guaranteed, as recv() may receive fewer bytes!). A better design is to have the server send strings that have a terminating delimiter at the end, such as a line break or a null terminator, and then have the client read in a loop until it receives that delimiter, THEN process the data that has been received.
Try something more like this:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
//Winsock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "Winsock Startup Failed, Error " << iResult << std:endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = inet_addr("10.0.1.2"); //Address to be connected to
addr.sin_port = htons(139); //Port = 139
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to establish new connection with
if (Connection == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
WSACleanup();
return 1; //Failed to Connect
}
if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //If we are unable to connect...
{
iResult = WSAGetLastError();
std::cout << "Failed to Connect, Error " << iResult << std::endl;
closesocket(Connection);
WSACleanup();
return 1; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char buf[256], *ptr, *start, *end;
int numRead;
std::string MOTD;
int iExitCode = 0;
while (true)
{
numRead = recv(Connection, buf, sizeof(buf), NULL); //Receive data
if (numRead == SOCKET_ERROR)
{
iResult = WSAGetLastError();
std::cout << "Failed to Read, Error " << iResult << std:endl;
iExitCode = 1;
break;
}
if (numRead == 0)
{
std::cout << "Server disconnected!" << std::endl;
break;
}
start = buf;
end = buf + numRead;
do
{
// look for MOTD terminator
ptr = std::find(start, end, '\0');
if (ptr == end)
{
// not found, need to read more...
MOTD.append(start, end-start);
break;
}
// terminator found, display current MOTD and reset for next MOTD...
MOTD.append(start, ptr-start);
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
MOTD = "";
start = ptr + 1;
}
while (start < end);
}
closesocket(Connection);
WSACleanup();
return iExitCode;
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
bool sendAll(SOCKET s, const void *buf, int size)
{
const char *ptr = (const char*) buf;
while (size > 0)
{
int numSent = send(s, ptr, size, NULL);
if (numSent == SOCKET_ERROR) return false;
ptr += numSent;
size -= numSent;
}
return true;
}
int main()
{
//WinSock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "WinSock Startup Failed, Error " << iResult << std::endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = INADDR_ANY; //Address that we will bind our listening socket to. INADDR_ANY = all local IPv4 addresses
addr.sin_port = htons(139); //Port
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to listen for new connections
if (sListen == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket
{
iResult = WSAGetLastError();
std::cout << "Failed to Bind Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Outstanding Max Connections
{
iResult = WSAGetLastError();
std::cout << "Failed to Listen, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
SOCKET newConnection; //Socket to hold the client's connection
int iExitCode = 0;
do
{
std::cout << "Waiting for Client to Connect..." << std::endl;
int addrlen = sizeof(addr); //length of the address (required for accept call)
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == INVALID_SOCKET) //If accepting the client connection failed
{
iResult = WSAGetLastError();
std::cout << "Failed to accept a client's connection, Error " << iResult << std::endl;
iExitCode = 1;
break;
}
std::cout << "Client Connected!" << std::endl;
for (int counter = 0; counter < 100; ++counter)
{
std::string MOTD = "Hi there."; //Create buffer with message
if (!sendAll(newConnection, MOTD.c_str(), MOTD.length()+1))
{
iResult = WSAGetLastError();
std::cout << "Failed to Send, Error " << iResult << std::endl;
break;
}
}
closesocket(newConnection);
std::cout << "Client Disconnected!" << std::endl;
}
while (true);
closesocket(sListen);
WSACleanup();
return iExitCode;
}
Thank you for all the answers and comments! I solved the problem via changing the port number. Apparently, some of the port numbers are reserved so I have to assign another one.
I am attempting to read RSysLog log from a machine running debian linux. I have setup a server on another linux machine and can read the log messages. I want to be able to read them on a windows machine from c++. I have setup the remote machine to distribute the logs to the windows machine. I have an application running on the machine that writes log messages at intervals. The setup to distribute the logs is of the form local1.* ##192.168.1.8 which is the ip address of the windows machine.
I know I am not thinking about this correctly, the remote machine does not attempt a connection to the windows machine and the program hangs on the accept call.
Edit:
After some further testing I figured out that the connect occurs when the syslog daemon is started. To use tcp the server has to be alive when the daemon is started. This is not what I want so I will work more with the UDP implementation.
Here is the code I am using, I have tried to make it as simple as possible.
WSADATA wsaData;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
SOCKET h;
h = socket(AF_INET, SOCK_STREAM, 0);
if (h == INVALID_SOCKET)
{
std::cout << "Socket Failure: " << std::endl;
return 1;
}
std::cout << "Socket Success: " << std::endl;
// The server
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("192.168.1.8");
server.sin_port = htons(514);
iResult = bind(h, (SOCKADDR *)&server, sizeof(server));
if (iResult == SOCKET_ERROR)
{
std::cout << "Bind Failure: " << std::endl;
closesocket(h);
return 1;
}
std::cout << "Bind Success: " << std::endl;
if (listen(h, SOMAXCONN))
{
std::cout << "Listen Failure: " << std::endl;
errcode = WSAGetLastError();
closesocket(h);
return 1;
}
std::cout << "Listen Success: " << std::endl;
struct sockaddr_in dest;
int addrlen = sizeof(dest);
SOCKET s = accept(h, (sockaddr *)&dest, &addrlen);
if (s == INVALID_SOCKET)
{
std::cout << "Accept Failure: " << std::endl;
}
else
{
std::cout << "Accept Success: " << std::endl;
}
WSACleanup();
return 0;
You probably need SOCK_DGRAM instead of SOCK_STREAM.
Syslog on port 514 seems to send UDP packets, not TCP.
You could also try to connect to the server with a browser to check if all the rest is ok (seems ok though) - 192.168.1.8:514 (while still in TCP mode).
I am trying to implement a small c++ server. i want to receive connections from clients, and handle all of these connections in own threads. So far so good. As long as i introduce no threads, it works fine, but as soon as i try to create a thread for a client, accept returns with -1/error.
Here is my code:
void Server::run()
{
cout << "starting server on port " << this->port << "..." << endl;
this->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (this->socket_fd < 0) {
perror("creating socket");
exit(1);
}
struct sockaddr_in myaddr;
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(this->port);
inet_aton("192.168.201.58", &myaddr.sin_addr);
if ( bind(this->socket_fd, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
perror("bind");
exit(1);
}
if (listen(this->socket_fd, 5)) {
perror("listen");
exit(1);
}
/* waiting for clients */
cout << "waiting for connection..." << endl;
int client_fd;
struct sockaddr_in remote_addr;
socklen_t remote_addr_len;
while (this->running) {
client_fd = accept(this->socket_fd, (struct sockaddr*)&remote_addr, &remote_addr_len);
if (client_fd <= 0) {
perror("accept");
this->running = false;
continue;
}
cout << "got new client with address " << inet_ntoa(remote_addr.sin_addr) << endl;
Client new_client(client_fd, remote_addr.sin_addr);
//new_client.run();
std::thread t ( &Client::run, &new_client );
//t.detach();
}
}
when I am trying to connect via telnet, I get "accept: Invalid argument". As soon as I comment out the line where I create the thread
std::thread t ( &Client::run, &new_client );
everything works fine.
I would appreciate any hints.
Try:
std::thread t ( &Client::run, std::move(new_client) );
According to the documentation, that's how you should call it.