C++ TCP IP Client, send/recv messages overlap? - c++

I am currently trying to create a C++ TCP IP Client that can send a specific string to a server, which makes the server send back a string with some numbers I need to use.
Specifically I need to send the string "getpos", and only that.
This works perfectly on the first loop, but on the second loop and onward. Whenever I try to send "getpos" again, it will overlap "getpos" with the numbers I previously recieved from the server and send that like:
"getpos20,123,24"
It's like the buffer or something hasn't cleared.
My program works perfectly when connecting to a Python server, but not a C++ server.
I have looked through others with similar issues, and tried various fixes. Nothing has worked so far.
Here is my current client code (on Linux):
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
int main()
{
// Create a socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
return 1;
}
// Create a hint structure for the server we're connecting with
int port = PORTHERE;
std::string ipAddress = "IPNUMBERHERE";
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
std::cout << "listening" << std::endl;
// Connect to the server on the socket
int connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connectRes == -1)
{
return 1;
}
std::cout << "connected" << std::endl;
// While loop:
char buf[4096];
int buflen = 1024;
while(true){
// Send to server
std::string getmypos = "getpos";
int sendRes = send(sock, getmypos.c_str(), getmypos.size(), 0);
if (sendRes == -1){
std::cout << "Could not send to server! Whoops!" << std::endl;
continue;
}
// Wait for response
memset(buf, 0, 4096);
int bytesReceived = recv(sock, buf, buflen, 0);
if (bytesReceived == -1)
{
std::cout << "There was an error getting response from server" << std::endl;
}
else
{
// Display response
std::cout << "SERVER> " << std::string(buf, bytesReceived) << std::endl;
sleep(1);
}
}
// Close the socket
close(sock);
return 0;
}

Related

C++ socket communication with an external device

So I've an industrial controller here and I wish to communicate with this device using my pc (windows 10), over ethernet tcp/ip.
This external device (controller) is connected directly to my pc via an ethernet cable and both my pc and the external device have a static IP address within the same range.
The manufacturer of this device has its own software with which I can communicate with the device over ethernet tcp/ip, however that is for configuring and programming the device.
I would like to make a small client application that uses sockets to send some command to this controller and should read the response from the device. The device is functioning as a server.
Important to know is that the commands should be sent in hexadecimal form to the device and it responds back with a message in hexadecimal form.
I am coding this in c++ in a visual studio 2022 environment.
So far I can connect to the external device (server), but sending the command and reading the response does not seem it be working.
Another issue is that the error messages are not displayed in the console, even when I add a delay of 2 seconds everywhere.
Below is my code:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment (lib, "Ws2_32.lib")
#include <iostream>
#include <string.h>
#include <sstream>
#include <WinSock2.h>
#include <WS2tcpip.h>
using namespace std;
int main()
{
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
cout << " Winsocket connection failed!" << endl;
Sleep(2000);
exit(1);
}
SOCKADDR_IN address;
int addressLen = sizeof(address);
IN_ADDR ipvalue;
address.sin_addr.s_addr = inet_addr("192.168.0.10");
address.sin_port = htons(9100);
address.sin_family = AF_INET;
SOCKET connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(connection, (SOCKADDR*)&address, addressLen) == 0)
{
cout << "Connected" << endl;
Sleep(2000);
}
else
{
cout << "Error connecting to server" << endl;
Sleep(2000);
exit(1);
}
char buffer[4096];
string getInput;
do
{
cout << ">input:";
getline(cin, getInput);
if (getInput.size() > 0)
{
// send message
int sendResult = send(connection, getInput.c_str(), getInput.size() + 1, 0);
if (sendResult != SOCKET_ERROR)
{
// Wait for response from server
ZeroMemory(buffer, 4096);
int bytesReceived = recv(connection, buffer, 4096, 0);
if (bytesReceived)
{
// Response to client
cout << "SERVER> " << string(buffer, 0, bytesReceived) << endl;
Sleep(2000);
}
else
cout << "error " << endl;
Sleep(2000);
}
}
}
while (getInput.size() > 0);
}

C++ chat client receives only after sending a message himself

I am trying to write a little tcp chatroom in c++. When I connect one client to the server, the server receives correctly and can answer/echo if wanted. When I connect a second client and send a message with him to the server the other client receives that message too. But to receive the next messages of the other clients
When I have two clients connected to the server and the first client (C1) is sending, the other client (C2) receives that message correctly too. But from that point, that client (C2) has to send something himself in order to receive another message from client (C1). And the other way around. I hope thats understandable.
I thought that it has something to do with the fact that the "getline" is blocking from continueing to receiving again, so I tried to use threads but that didnt work either. Now I am thinking that I really has something to do with the streaming "property" of TCP.
Here is the server code:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <sys/select.h>
#include <fcntl.h>
#include <vector>
#include <thread>
using namespace std;
int main() {
// create server-socket
int listening = socket(AF_INET, SOCK_STREAM, 0);
fcntl(listening, F_SETFL, O_NONBLOCK);
if (listening == -1) {
cerr << "Failed to create socket." << endl;
return -1;
}
// bind socket to ip/port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
inet_pton(AF_INET, "0.0.0.0", &hint.sin_addr);
// check if can bind
if (bind(listening, (sockaddr*)&hint, sizeof(hint)) == -1) {
cerr << "Failed to bind to IP/port" << endl;
return -2;
}
// check if can listen
if (listen(listening, SOMAXCONN) == -1) {
cerr << "Failed to listen." << endl;
return -3;
}
//
fd_set master;
FD_ZERO(&master);
FD_SET(listening, &master);
while (true) {
for (int i=0; i<=FD_SETSIZE; i++) {
if (FD_ISSET(i, &master)) {
int sock = i;
if(sock == listening) {
sockaddr_in client;
socklen_t clientSize = sizeof(client);
char host[NI_MAXHOST];
char svc[NI_MAXSERV];
int clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
FD_SET(clientSocket, &master);
string acceptMessage = "Successfully connected to the server.";
send(clientSocket, acceptMessage.c_str(), (acceptMessage.size() + 1), 0);
}
else {
char buffer[4096];
memset(buffer, 0, 4096);
// receive from client
int bytesReceived = recv(sock, buffer, 4096, MSG_DONTWAIT);
if (bytesReceived == -1) {
;
}
else if (bytesReceived == 0) {
close(sock);
FD_CLR(sock, &master);
cout << "Client disconnected." << endl;
}
else {
cout << "received: " << string(buffer, 0, bytesReceived) << endl;
for (int j=0; j<100; j++) {
int outSock = j;
if (FD_ISSET(j, &master)) {
if (outSock != listening && outSock != 63) {
if (outSock == sock) {
string echoMsg = "<echo>" + string(buffer, 0, bytesReceived);
send(outSock, echoMsg.c_str(), (echoMsg.size() + 1), 0);
;
}
else {
send(outSock, buffer, bytesReceived, 0);
}
}
}
}
}
}
}
}
}
return 0;
}
Here the client code:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <fcntl.h>
#include <future>
#include <thread>
using namespace std;
void *sendMessage(string userInput, int sock);
void *receiveMessage(char buffer[4096], int sock);
void *sendMessage(string userInput, int sock) {
// input message to send
cout << ">> ";
getline(cin, userInput);
// send message
int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0);
if (sendResult == -1) {
cout << "Could not send to server." << endl;
}
}
void *receiveMessage(char buffer[4096], int sock) {
int bytesReceived = recv(sock, buffer, 4096, 0);
if (bytesReceived == -1) {
cout << "There has been a server-issue." << endl;
}
else if (bytesReceived == 0) {
cout << "Server closed." << endl;
}
else {
string receivedString = string(buffer, 0, bytesReceived);
string checkEcho = receivedString.substr(0, 6);
if (checkEcho.compare("<echo>") == 0) {
;
}
else {
cout << "SERVER: " << string(buffer, bytesReceived) << endl;
}
}
}
int main() {
// create socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
//fcntl(sock, F_SETFL, O_NONBLOCK);
if (sock == -1) {
return 1;
}
// port and server-ip
int port = 54000;
string ipAddress = "127.0.0.1";
// create buffer for messages
char buffer[4096];
// ipv4 socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
// try connect to server
int connectResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connectResult == -1) {
cout << "Could not connect to server." << endl;
return -1;
}
else {
receiveMessage(buffer, sock);
}
string userInput;
while (true) {
// receive from server
memset(buffer, 0, 4096);
thread t1(sendMessage, userInput, sock);
thread t2(receiveMessage, buffer, sock);
//sendMessage(userInput, sock);
//receiveMessage(buffer, sock);
t1.join();
t2.join();
}
// close socket
close(sock);
return 0;
}
I have found some similiar questions but none could help me solve my problem.
This bugs me for quite some time now, so I'd really appreciate some answers :)

Sockets not sending data

I'm currently working on an instant messaging system that require a server and a client to communicate between each other.
I tried it in C++ using the default socket API.
The problem is that even if both programs (server & client) compile fine, there isn't any socket sent from the client that reaches the server.
I don't know what did I do wrong here (I went over my code like 5 times and even did it again from scratch, no success).
I used "debugs" messages to locate the problems and they all concern the processing loops that I use.
// code from the server
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
const unsigned short port = 9999;
sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
res = listen(server, SOMAXCONN);
if (res != 0)
{
std::cout << "Error on calling listen";
return -4;
}
std::cout << "Server successfully launched" << std::endl;
char buffer[1025];
while (true)
{
sockaddr_in from = { 0 };
int addrlen = sizeof(from);
SOCKET newClient = accept(server, (SOCKADDR*)(&from), &addrlen);
if (newClient != SOCKET_ERROR)
{
std::cout << "Client connected successfully" << std::endl;
int Bytes = recv(newClient, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "Message received from client : " << buffer << std::endl;
send(newClient, buffer, 1024, 0); // send it back to client
}
}
return 0;
}
// code from the client
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
void sendMessage(SOCKET s);
void recvMessage(SOCKET s);
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
std::cout << "You are connected to server" << std::endl;
std::thread sending(sendMessage, server);
std::thread receiving(recvMessage, server);
sending.detach();
receiving.detach();
while (true)
{ }
return 0;
}
void sendMessage(SOCKET s)
{
while (true)
{
std::string buff;
std::cout << "Type your message :" << std::endl;
std::getline(std::cin, buff);
std::cout << std::endl;
int Bytes = send(s, buff.c_str(), 1024, 0);
if (Bytes <= 0)
{
break;
}
}
}
void recvMessage(SOCKET s)
{
while (true)
{
char buffer[1025];
int Bytes = recv(s, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "The server sent : " << buffer << std::endl;
}
}
The server should display the message that a client has connected when the client is launched and displays the chat command, but the only thing displayed in the server console is the message saying that the server has launched correctly... Yet the client displays the message supposedly "received" by the server.
PS : I'm aware the code doesn't need that many "include" statements, it's just I didn't remember which ones contained which functions so I'd rather include more than not enough for anybody wanting to compile the code.
Several Things:
First, this is wrong:
send(s, buff.c_str(), 1024, 0)
You're basically telling send that the buffer it addresses is a full 1kb, and to send it all. It hasn't a clue how much memory there is actually valid, and knows nothing about terminated strings.
Second, the client setup is wrong. Don't bind to a client socket; connect is sufficient. Notice these:
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
That bind shouldn't be there. The connect will bind to the socket if the connection can be made. Removing the bind section of the client, fixing the buffer management to be correct, and putting closesocket calls where they belong, and your program will be much further down the road to functional. There are still some question logic workflows, but at least the connectivity will be setup better.

libev + non-blocking socket continuously invokes callback

I'm using libev + non-blocking sockets to send a request to a server. I'm using Keep Alive because I need to send future requests to the destination over this same connection.
Behavior
Run the program and it fetches the URL and logs to console, as expected.
After doing this, wait and don't push ctrl+c to exit the program.
Expected
App should stay open because event loop is waiting for future responses but should not console log anything after the initial response.
Actual
Leave the app running. After 30+ seconds, it will start to console log the same response over and over and over again without end.
Question
Why is libev calling my callback (example_cb) repeatedly when no new request was sent and no new response data was received? How can I fix this?
#include <ev.h>
#include <stdio.h>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
void sendRequest(int sockfd)
{
puts("------");
puts("sendRequest() was called");
stringstream ss;
ss << "GET /posts/11 HTTP/1.1\r\n"
<< "Host: jsonplaceholder.typicode.com\r\n"
<< "Accept: application/json\r\n"
<< "\r\n";
string request = ss.str();
if (send(sockfd, request.c_str(), request.length(), 0) != (int)request.length()) {
cout << "Error sending request." << endl;
exit(1);
}
cout << "Request sent. No err occured." << endl;
}
static void delay_cb(EV_P_ ev_timer *w, int revents)
{
puts("------");
puts("delay_cb() was called");
sendRequest(3);
}
static void example_cb(EV_P_ ev_io *w, int revents)
{
puts("------");
puts("example_cb() was called");
int sockfd = 3;
size_t len = 80*1024, nparsed; // response must be <= 80 Kb
char buf[len];
ssize_t recved;
recved = recv(sockfd, &buf, len, 0);
if (recved < 0) {
perror("recved was <1");
}
// don't process keep alives
if (buf[0] != '\0') {
std::cout << buf << std::endl;
}
// clear buf
buf[0] = '\0';
std::cout << "buf after clear attempt: " << buf << std::endl;
}
int example_request()
{
std::string hostname = "jsonplaceholder.typicode.com";
int PORT = 80;
struct sockaddr_in client;
struct hostent * host = gethostbyname(hostname.c_str());
if (host == NULL || host->h_addr == NULL) {
cout << "Error retrieving DNS information." << endl;
exit(1);
}
bzero(&client, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons( PORT );
memcpy(&client.sin_addr, host->h_addr, host->h_length);
// create a socket
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
cout << "Error creating socket." << endl;
exit(1);
}
cout << "Socket created" << endl;
// enable keep alive
int val = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof val);
if (connect(sockfd, (struct sockaddr *)&client, sizeof(client)) < 0) {
close(sockfd);
cout << "Could not connect" << endl;
exit(1);
}
cout << "Socket connected" << endl;
// make non-blocking
int status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
if (status == -1) {
perror("ERROR making socket non-blocking");
}
std::cout << "Socket set to non-blocking" << std::endl;
std::cout << "Sockfd is: " << sockfd << std::endl;
return sockfd;
}
int main(void)
{
// establish socket connection
int sockfd = example_request();
struct ev_loop *loop = EV_DEFAULT;
ev_io example_watcher;
ev_io_init(&example_watcher, example_cb, sockfd, EV_READ);
ev_io_start(loop, &example_watcher);
// used to send the request 2 sec later
ev_timer delay_watcher;
ev_timer_init(&delay_watcher, delay_cb, 2, 0.0);
ev_timer_start(loop, &delay_watcher);
ev_run(loop, 0);
return 0;
}
Edit: Code updated with suggestions from comments
The source of the problem is that you do not check recved == 0 condition which corresponds to the other side closing the connection. When that happens the OS sets the socket into "closed mode" which (at least under linux) is always ready for reading and subsequent calls to recv will always return 0.
So what you need to do is to check for that condition, call close(fd); on the file descriptor (possibly with shutdown before) and ev_io_stop on the associated watcher. If you wish to continue at that point then you have to open a new socket and eo_io_start new watcher.

TCP/IP What happens when client sends data after server crash?

I'm trying to test how to handle a client when a client sends data after a tcp server crash. I wrote a simple client and server code to provide some visual example. The client connects to the tcp server, sends data to the server, and the server reads the data.
Now I add a sleep(20) to both implementations so I have time to kill the server process (ctrl-c).
The client calls send() again and returns the length of the message. The server is not connected so probably the client will not receive a ACK packet. I assume that the client gets a RST packet but the send() has already returned. The client calls send() a 3rd time but this time, the process ends abruptly without showing any error. The last lines: cout << rsize << endl and everything below it are never called or at least that's what looks like.
When I run this, the client prints rsize values for the first two messages, but not the last one. The server prints only the first message received.
My questions are (1) why is this happening?, and (2)how can I handle correctly a server crash if the client ends abruptly?
I already read other questions related to the topic, but they don't show actual code of how to handle this.
Client code
#include <iostream>
#include <cerrno>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int serverPort = 65003;
char serverHost[] = "127.0.0.1";
int mySocket;
int bufferSize = 524388;
char responseBuffer[bufferSize];
struct sockaddr clientAddr;
struct sockaddr_in serverAddr;
struct in_addr ipv4addr;
serverAddr.sin_family = AF_INET;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
serverAddr.sin_port = htons (serverPort);
inet_aton(serverHost, &serverAddr.sin_addr);
connect(mySocket, (struct sockaddr*) &serverAddr, sizeof(serverAddr));
int addrLen = sizeof(serverAddr);
getsockname(mySocket, &clientAddr, (socketlen_t*)&addrLen);
ssize_t rsize;
char requestMsg [] = "<This is my test Msg>";
cout << rsize << endl;
rsize = send(mySocket, requestMsg, strlen(requestMsg), 0);
if (rsize != (ssize_t)strlen(requestMsg))
{
cout << strlen(requestMsg) << endl;
cout << strerror(errno) << endl;
}
sleep(20);
char requestMsg2 [] = "<This is my 2nd test Msg>";
rsize = send(mySocket, requestMsg2, strlen(requestMsg2), 0);
cout << rsize << endl;
if (rsize != (ssize_t)strlen(requestMsg2))
{
cout << strlen(requestMsg2) << endl;
cout << strerror(errno) << endl;
}
char requestMsg3 [] = "<This is my 3rd test Msg>";
rsize = send(mySocket, requestMsg3, strlen(requestMsg3), 0);
cout << rsize << endl;
if (rsize != (ssize_t)strlen(requestMsg3))
{
cout << strlen(requestMsg3) << endl;
cout << strerror(errno) << endl;
}
return 0;
}
server code
#include <iostream>
#include <cerrno>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int mySocket, connSocket, serverPort;
socketlen_t clientLen;
struct sockaddr_in serverAddr, clientAddr;
int bufferSize = 256;
char buffer[bufferSize];
ssize_t rsize;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&serverAddr, 0, sizeof(serverAddr));
serverPort = 65003;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(serverPort);
bind(mySocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
listen(mySocket,1);
clientLen = sizeof(clientAddr);
connSocket = accept(mySocket, (struct sockaddr *) &clientAddr, &clientLen);
memset(&buffer, 0, sizeof(buffer));
rsize = read(connSocket, buffer, 255);
cout << buffer << endl;
sleep(20);
}