I am trying to solve a root-me.org challenge, it is a pretty easy one but i am still stuck and cannot figure out what the problem is. The problem :
Statement
To start this test using the TCP protocol, you need to connect to a program on a network socket.
Calculate the square root of number 1 and multiply by number 2.
Then round the result to two decimal places.
You have 2 seconds to send the correct answer from the moment the program sends you the calculation.
The answer must be sent in the form of int
According to what I have discovered so far the issue lies with the part where I try to send my response to the server.
Link to the challenge I am trying to solve : https://www.root-me.org/en/Challenges/Programming/TCP-Back-to-school
I have tried four different ways to send the answer to send my answer : using a float, a string and an integer, at one point only I got a response from the server, it said that I sended the wrong type, "answer has to be int or float", I don't even remember how I did to get that response.
Additionally, note that I am only able to send strings with the right value and precision as floats lack too much precision in c++. For example: sending doubles results in sending a number with the right precision (38559.390000) but the decimals are filled up by "0" sending float results in wrong result : (8807.008807) sending string works but apparently the server doesn't support it.
My code :
// TCP - Retour au collège
#include <sys/socket.h>
#include <iostream>
#include <cmath>
#include <cstring>
#include <netinet/in.h>
#include <unistd.h>
#include <iomanip>
#include <arpa/inet.h>
#include <string>
int main() {
// Connect to root-me.org with tcp (this script is client side)
int client = socket(AF_INET6, SOCK_STREAM, 0);
// set socket address type to network type
struct sockaddr_in6 serv;
std::memset(&serv, 0, sizeof(serv));
// set type to ipv6
serv.sin6_family = AF_INET6;
// Set port
serv.sin6_port = htons(52002);
//convert to bin and add actual adress
inet_pton(AF_INET6, "2001:bc8:35b0:c166::151", &serv.sin6_addr);
// Bind the client to the parameters
connect(client, (struct sockaddr*)&serv, sizeof(serv));
std::cout << "port 52002" << std::endl;
//Receive data and processing
char buffer[1024] = { 0 };
recv(client, buffer, sizeof(buffer), 0);
std::cout << "Message from serv: " << buffer << std::endl;
std::string str = buffer;
size_t startPos1 = str.find("square root of ") + strlen("square root of ");
size_t startPos2 = str.find(" and multiply by ") + strlen(" and multiply by ");
size_t endPos1 = str.find(" and multiply by ") - 1;
size_t endPos2 = str.find(" =") - 1;
std::string number1 = str.substr(startPos1, endPos1 - startPos1 + 1);
int number1_ = std::stoi(number1);
std::string number2 = str.substr(startPos2, endPos2 - startPos2 + 1);
int number2_ = std::stoi(number2);
double res = (std::sqrt((number1_))) * number2_; //static_cast<double>
std::cout << std::setprecision (15) << res << std::endl;
//seend - HERE I TRIED MANY DIFFERENT THINGS, SENDING A STRING, A DOUBLE AND A FLOAT
//float res_ = static_cast<float>(res);
//std::cout << res_ << std::endl;
//std::string res_=std::to_string(res);
//res_.erase(res_.size() - 4);
//std::cout << "string:" << res_ << std::endl;
//char buffer2[sizeof(res_)];
//std::memcpy(buffer2, &res_, sizeof(res_));
res = std::ceil(res * 100.0) / 100.0;
std::string a = std::to_string(res);
size_t pos = (a.find(".")+3);
std::string b = a.substr(0, pos);
std::cout << b << std::endl;
const char* message = b.c_str();
send(client, message, strlen(b.c_str()), 0);
std::cout << "sent :" << b.c_str() << ";" << message << std::endl;
//Response?
char buffer1[1024] = { 0 };
recv(client, buffer1, sizeof(buffer1), 0);
std::cout << "Message from serv: " << buffer1 << std::endl;
//closing&ending
close(client);
return 0;
}
The outputs : THE ONLY TIME I GOT A RESPONSE FROM SERV :
port 52002
Message from serv:
====================
GO BACK TO COLLEGE
====================
You should tell me the answer of this math operation in less than 2 seconds !
Calculate the square root of 1 and multiply by 8807 =
8807.00
sent :8807.008807
Message from serv: [!] Please only send int/float !
Out 1 -
port 52002
Message from serv:
==================== GO BACK TO COLLEGE====================
You should tell me the answer of this math operation in less than 2 seconds !
Calculate the square root of 207 and multiply by 2092 =
30098.6386403106
sent :30098.64
Out 2 -
port 52002
Message from serv:
====================
GO BACK TO COLLEGE
====================
You should tell me the answer of this math operation in less than 2 seconds !
Calculate the square root of 120 and multiply by 3958 =
43357.7176521089
43357.72
sent :43357.72;43357.72
Out 3 -
port 52002
Message from serv:
====================
GO BACK TO COLLEGE
====================
You should tell me the answer of this math operation in less than 2 seconds !
Calculate the square root of 87 and multiply by 4134 =
38559.3850054692
string:38559.39
sent :38559.39;38559.390000
Out 4 -
port 52002
Message from serv:
====================
GO BACK TO COLLEGE
====================
You should tell me the answer of this math operation in less than 2 seconds !
Calculate the square root of 56 and multiply by 9112 =
68187.9642165683
68187.97sent :68187.97;R�����@R�����@�x�
Okay, I actually solved it by coding the solution in python and thus unlocking the "solutions" category of website where I could find a version of the code in C that i used to inspire me.
Here is basically what I did (without spoiling) :
First I deleted the part between the two following code samples and restarted from scratch for the sending of the data as it is just an enormous mess
double res = (std::sqrt((number1_))) * number2_; //static_cast<double>
std::cout << std::setprecision (15) << res << std::endl;
===============================DELETE=========================================
//Response?
char buffer1[1024] = { 0 };
At the end of the processing of the data I output a double
double res = (std::sqrt((number1_))) * number2_; //static_cast<double>
After what I use "osstring":std::ostringstream oss;
to define "oss", i then assign the double "res" to "oss" (something like oss << [...] << std::setprecision(2) << res
) That forces the string "oss" to have 2 decimals and they are accurate because I was using a double, which is more accurate than a float object in c++.
I then send back my data (after changing it from oss to a std::string ofc) : send(client, strn.c_str(), strlen(strn), 0);
Finally, I listen for the servers response as shown in the code above.