TCP server message extra characters c++
I think I am missing something and doesn't make sense.
I am writing pretty simple TCP server, everything works pretty much as expected, but when a message saying "500 LOGIN FAILED" gets send over network, it get interpreted as "$500 LOGIN FAILED".
I am testing my server using telnet on localhost
here is simplified version of my code
recv(c_sockfd, buf, BUFFSIZE, 0))
inBuffer.push_back(buf);
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
in the checkResponse func, I am implementing logic to decide what message to send, and somehow when I send ERROR message the extra character is added at the beginning of the message.
EXAMPLE 1:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
674rn
202 OK
INFO iasdijasdjiajsdiajdijasidjiansdjsdvhdf dfvsdfsdfrn
&501 SYNTAX ERROR
Notice the "&" character
EXAMPLE 2:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
456rn
$500 LOGIN FAILED
Notice the "$" character
Does anyone have any idea where the extra characters could be added to the string?
I didn't want to include full code, because the requirement was to have all in one file, which makes it difficult to read. Here it goes tho.
FULL CODE:
#include <iostream>
#include <regex>
#include <iterator>
#include <vector>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <tuple>
#define MIN_PORT 3000
#define MAX_PORT 3999
#define BUFFSIZE 1000
/**
0 - LOGIN SUCCESSFUL, USERNAME IS IN THE BUFFER
1 - PASSWORD CHECK
2 - PASSWORD OK, COMMUNICATING
*/
int state = 0;
std::string username, password;
/**
CHECKS ENTERED PASSWORD BASES ON THE SUM OF ASCII VALUES OF USERNAME
@return: true on success, false otherwise
*/
bool checkPassword(std::string password){
std::istringstream sst;
sst.str(username);
unsigned char byte = '';
int value = 0;
// std::cout << "byte poprve: " << byte << std::endl;
// std::cout << "byte poprve INT: " << (int) byte << std::endl;
while (sst >> byte) {
std::cout << "podruhe: " << byte << std::endl;
std::cout << "podruhe INT: " << (int) byte << std::endl;
std::cout << "Prubezna SUMA: " << (int) value << std::endl;
value += byte;
}
std::cout << "suma: " << value << std::endl;
// Check the entered password
if (password == std::to_string(value)) {
return true;
}
return false;
}
/**
CHECKS MESSAGE SYNTAX BASED ON THE STATE WE ARE IN
CHECKS PASSWORD
CHECKS CHECK SUM
@param response <string type (if available), string message to parse>
@return TRUE on success, FALSE otherwise
*/
bool checkMessage(std::tuple<std::string,std::string> response){
auto messageToParse = std::get<1>(response);
std::string delimeter = "rn";
std::string::size_type pos = messageToParse.find(delimeter);
//INITIAL CHECK
if (pos < 1){
return false;
}
//somehow you have to multiply the length by 2
auto parsedMessage = messageToParse.substr(0,pos - 2*delimeter.length());
std::cout << parsedMessage << " : THIS IS YOUR PARSED MESSAGE";
//USERNAME
if (state == 0) {
username = parsedMessage;
return true;
}
//PASSWORD CHECK
if (state == 1 && checkPassword(parsedMessage)) {
password = parsedMessage;
return true;
}
if (state == 2) {
std::string type = std::get<0>(response);
//INFO
if( type == "I" ){
return true;
}
//PHOTO
if ( type == "F") {
return true;
}
}
return false;
}
/**
THIS FUNC WILL CHECK RESPONSE FROM THE ROBOT, AND DECIDE WHAT TO DO BASED ON THE STATE
@return tuple<bool TRUE if everything is right,std::string MESSAGE to send to the robot>
*/
std::tuple<bool,std::string> checkResponse(std::tuple<std::string, std::string> response){
if (state == 0) {
if (checkMessage(response)) {
std::cout << state << " / / state" << std::endl;
return std::make_tuple(true, "201 PASSWORDrn");
}
}
if (state == 1) {
// TADY BUDE JESTE PODMINKA, ZE HESLO JE SPRAVNE
if(checkMessage(response)){
std::cout << state << " / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / state" << std::endl;
return std::make_tuple(false, "500 LOGIN FAILEDrn");
}
}
if (state == 2) {
if (checkMessage(response)) {
std::cout << state << " / / / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / / / state" << std::endl;
return std::make_tuple(false, "501 SYNTAX ERROR rn");
}
}
std::cout << state << " / / / / / / / / state" << std::endl;
return std::make_tuple(false, "unexpected result");
}
/**
This func will parse the incoming buffer
@param buffer incoming buffer
@return tuple <String type of message (U,I,P,F), String actual message>
*/
std::tuple<std::string, std::string> parseBuffer(std::string buffer){
if (state == 0) {
return std::make_tuple("U", buffer);
}
if (state == 1) {
return std::make_tuple("P", buffer);
}else{
std::string delimeter = " ";
std::string::size_type pos = buffer.find(delimeter);
std::string type = buffer.substr(0, pos );
std::string message = buffer.erase(0, pos + delimeter.length());
return std::make_tuple(type, message);
}
}
int main(int argc, char *argv)
{
char buf[BUFFSIZE];
std::vector<std::string> outBuffer;
std::vector<std::string> inBuffer;
int sockfd, c_sockfd;
sockaddr_in my_addr, rem_addr;
socklen_t rem_addr_length;
int mlen;
const int PORT_NUM = atoi(argv[1]);
if( (PORT_NUM > MAX_PORT) || (PORT_NUM < MIN_PORT)){
perror("Port number is not acceptable");
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("Socket nelze otevrit");
exit(-1);
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT_NUM);
std::cout << PORT_NUM << " PORT NUM" << std::endl;
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
perror("Chyba v bind");
close(sockfd); exit(1);
}
if (listen(sockfd, SOMAXCONN) == -1)
{
perror("Nelze provest listen");
close(sockfd); exit(1);
}
while (1)
{
rem_addr_length=sizeof(rem_addr);
c_sockfd = accept(sockfd, (struct sockaddr*) &rem_addr, &rem_addr_length);
if ( c_sockfd == -1)
{
perror("Nelze accept");
close(sockfd); exit(1);
}
///FIRST MESSAGE
std::string ok = "200 LOGINrn";
send(c_sockfd, &ok, sizeof(std::string), 0);
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
perror("Chyba pri cteni");
else{
while (mlen)
{
///---------- MAIN PART--------------
//This is where comunication is happening
inBuffer.push_back(buf);
//Parse the buffer, check the message and
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
///---------- MAIN PART--------------
state++;
std::cout << state << " state num" << std::endl;
if (send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0) == -1)
{
perror("Chyba pri zapisu");
break;
}else{
}
std::cout << inBuffer.back() << std::endl;
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
{
perror("Chyba pri cteni");
break;
}
}
close(c_sockfd);
}
}
}
c++ sockets c++11 tcp telnet
|
show 1 more comment
I think I am missing something and doesn't make sense.
I am writing pretty simple TCP server, everything works pretty much as expected, but when a message saying "500 LOGIN FAILED" gets send over network, it get interpreted as "$500 LOGIN FAILED".
I am testing my server using telnet on localhost
here is simplified version of my code
recv(c_sockfd, buf, BUFFSIZE, 0))
inBuffer.push_back(buf);
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
in the checkResponse func, I am implementing logic to decide what message to send, and somehow when I send ERROR message the extra character is added at the beginning of the message.
EXAMPLE 1:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
674rn
202 OK
INFO iasdijasdjiajsdiajdijasidjiansdjsdvhdf dfvsdfsdfrn
&501 SYNTAX ERROR
Notice the "&" character
EXAMPLE 2:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
456rn
$500 LOGIN FAILED
Notice the "$" character
Does anyone have any idea where the extra characters could be added to the string?
I didn't want to include full code, because the requirement was to have all in one file, which makes it difficult to read. Here it goes tho.
FULL CODE:
#include <iostream>
#include <regex>
#include <iterator>
#include <vector>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <tuple>
#define MIN_PORT 3000
#define MAX_PORT 3999
#define BUFFSIZE 1000
/**
0 - LOGIN SUCCESSFUL, USERNAME IS IN THE BUFFER
1 - PASSWORD CHECK
2 - PASSWORD OK, COMMUNICATING
*/
int state = 0;
std::string username, password;
/**
CHECKS ENTERED PASSWORD BASES ON THE SUM OF ASCII VALUES OF USERNAME
@return: true on success, false otherwise
*/
bool checkPassword(std::string password){
std::istringstream sst;
sst.str(username);
unsigned char byte = '';
int value = 0;
// std::cout << "byte poprve: " << byte << std::endl;
// std::cout << "byte poprve INT: " << (int) byte << std::endl;
while (sst >> byte) {
std::cout << "podruhe: " << byte << std::endl;
std::cout << "podruhe INT: " << (int) byte << std::endl;
std::cout << "Prubezna SUMA: " << (int) value << std::endl;
value += byte;
}
std::cout << "suma: " << value << std::endl;
// Check the entered password
if (password == std::to_string(value)) {
return true;
}
return false;
}
/**
CHECKS MESSAGE SYNTAX BASED ON THE STATE WE ARE IN
CHECKS PASSWORD
CHECKS CHECK SUM
@param response <string type (if available), string message to parse>
@return TRUE on success, FALSE otherwise
*/
bool checkMessage(std::tuple<std::string,std::string> response){
auto messageToParse = std::get<1>(response);
std::string delimeter = "rn";
std::string::size_type pos = messageToParse.find(delimeter);
//INITIAL CHECK
if (pos < 1){
return false;
}
//somehow you have to multiply the length by 2
auto parsedMessage = messageToParse.substr(0,pos - 2*delimeter.length());
std::cout << parsedMessage << " : THIS IS YOUR PARSED MESSAGE";
//USERNAME
if (state == 0) {
username = parsedMessage;
return true;
}
//PASSWORD CHECK
if (state == 1 && checkPassword(parsedMessage)) {
password = parsedMessage;
return true;
}
if (state == 2) {
std::string type = std::get<0>(response);
//INFO
if( type == "I" ){
return true;
}
//PHOTO
if ( type == "F") {
return true;
}
}
return false;
}
/**
THIS FUNC WILL CHECK RESPONSE FROM THE ROBOT, AND DECIDE WHAT TO DO BASED ON THE STATE
@return tuple<bool TRUE if everything is right,std::string MESSAGE to send to the robot>
*/
std::tuple<bool,std::string> checkResponse(std::tuple<std::string, std::string> response){
if (state == 0) {
if (checkMessage(response)) {
std::cout << state << " / / state" << std::endl;
return std::make_tuple(true, "201 PASSWORDrn");
}
}
if (state == 1) {
// TADY BUDE JESTE PODMINKA, ZE HESLO JE SPRAVNE
if(checkMessage(response)){
std::cout << state << " / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / state" << std::endl;
return std::make_tuple(false, "500 LOGIN FAILEDrn");
}
}
if (state == 2) {
if (checkMessage(response)) {
std::cout << state << " / / / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / / / state" << std::endl;
return std::make_tuple(false, "501 SYNTAX ERROR rn");
}
}
std::cout << state << " / / / / / / / / state" << std::endl;
return std::make_tuple(false, "unexpected result");
}
/**
This func will parse the incoming buffer
@param buffer incoming buffer
@return tuple <String type of message (U,I,P,F), String actual message>
*/
std::tuple<std::string, std::string> parseBuffer(std::string buffer){
if (state == 0) {
return std::make_tuple("U", buffer);
}
if (state == 1) {
return std::make_tuple("P", buffer);
}else{
std::string delimeter = " ";
std::string::size_type pos = buffer.find(delimeter);
std::string type = buffer.substr(0, pos );
std::string message = buffer.erase(0, pos + delimeter.length());
return std::make_tuple(type, message);
}
}
int main(int argc, char *argv)
{
char buf[BUFFSIZE];
std::vector<std::string> outBuffer;
std::vector<std::string> inBuffer;
int sockfd, c_sockfd;
sockaddr_in my_addr, rem_addr;
socklen_t rem_addr_length;
int mlen;
const int PORT_NUM = atoi(argv[1]);
if( (PORT_NUM > MAX_PORT) || (PORT_NUM < MIN_PORT)){
perror("Port number is not acceptable");
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("Socket nelze otevrit");
exit(-1);
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT_NUM);
std::cout << PORT_NUM << " PORT NUM" << std::endl;
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
perror("Chyba v bind");
close(sockfd); exit(1);
}
if (listen(sockfd, SOMAXCONN) == -1)
{
perror("Nelze provest listen");
close(sockfd); exit(1);
}
while (1)
{
rem_addr_length=sizeof(rem_addr);
c_sockfd = accept(sockfd, (struct sockaddr*) &rem_addr, &rem_addr_length);
if ( c_sockfd == -1)
{
perror("Nelze accept");
close(sockfd); exit(1);
}
///FIRST MESSAGE
std::string ok = "200 LOGINrn";
send(c_sockfd, &ok, sizeof(std::string), 0);
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
perror("Chyba pri cteni");
else{
while (mlen)
{
///---------- MAIN PART--------------
//This is where comunication is happening
inBuffer.push_back(buf);
//Parse the buffer, check the message and
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
///---------- MAIN PART--------------
state++;
std::cout << state << " state num" << std::endl;
if (send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0) == -1)
{
perror("Chyba pri zapisu");
break;
}else{
}
std::cout << inBuffer.back() << std::endl;
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
{
perror("Chyba pri cteni");
break;
}
}
close(c_sockfd);
}
}
}
c++ sockets c++11 tcp telnet
1
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
2
What isoutBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.
– Some programmer dude
Nov 12 '18 at 10:20
My spidey-sense indicates thatoutBuffer
andinBuffer
are collections ofstd::string
.
– molbdnilo
Nov 12 '18 at 10:36
You're aware that TCP is a streaming protocol, and that you can receive any amount of data withrecv
, right?
– molbdnilo
Nov 12 '18 at 10:38
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40
|
show 1 more comment
I think I am missing something and doesn't make sense.
I am writing pretty simple TCP server, everything works pretty much as expected, but when a message saying "500 LOGIN FAILED" gets send over network, it get interpreted as "$500 LOGIN FAILED".
I am testing my server using telnet on localhost
here is simplified version of my code
recv(c_sockfd, buf, BUFFSIZE, 0))
inBuffer.push_back(buf);
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
in the checkResponse func, I am implementing logic to decide what message to send, and somehow when I send ERROR message the extra character is added at the beginning of the message.
EXAMPLE 1:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
674rn
202 OK
INFO iasdijasdjiajsdiajdijasidjiansdjsdvhdf dfvsdfsdfrn
&501 SYNTAX ERROR
Notice the "&" character
EXAMPLE 2:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
456rn
$500 LOGIN FAILED
Notice the "$" character
Does anyone have any idea where the extra characters could be added to the string?
I didn't want to include full code, because the requirement was to have all in one file, which makes it difficult to read. Here it goes tho.
FULL CODE:
#include <iostream>
#include <regex>
#include <iterator>
#include <vector>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <tuple>
#define MIN_PORT 3000
#define MAX_PORT 3999
#define BUFFSIZE 1000
/**
0 - LOGIN SUCCESSFUL, USERNAME IS IN THE BUFFER
1 - PASSWORD CHECK
2 - PASSWORD OK, COMMUNICATING
*/
int state = 0;
std::string username, password;
/**
CHECKS ENTERED PASSWORD BASES ON THE SUM OF ASCII VALUES OF USERNAME
@return: true on success, false otherwise
*/
bool checkPassword(std::string password){
std::istringstream sst;
sst.str(username);
unsigned char byte = '';
int value = 0;
// std::cout << "byte poprve: " << byte << std::endl;
// std::cout << "byte poprve INT: " << (int) byte << std::endl;
while (sst >> byte) {
std::cout << "podruhe: " << byte << std::endl;
std::cout << "podruhe INT: " << (int) byte << std::endl;
std::cout << "Prubezna SUMA: " << (int) value << std::endl;
value += byte;
}
std::cout << "suma: " << value << std::endl;
// Check the entered password
if (password == std::to_string(value)) {
return true;
}
return false;
}
/**
CHECKS MESSAGE SYNTAX BASED ON THE STATE WE ARE IN
CHECKS PASSWORD
CHECKS CHECK SUM
@param response <string type (if available), string message to parse>
@return TRUE on success, FALSE otherwise
*/
bool checkMessage(std::tuple<std::string,std::string> response){
auto messageToParse = std::get<1>(response);
std::string delimeter = "rn";
std::string::size_type pos = messageToParse.find(delimeter);
//INITIAL CHECK
if (pos < 1){
return false;
}
//somehow you have to multiply the length by 2
auto parsedMessage = messageToParse.substr(0,pos - 2*delimeter.length());
std::cout << parsedMessage << " : THIS IS YOUR PARSED MESSAGE";
//USERNAME
if (state == 0) {
username = parsedMessage;
return true;
}
//PASSWORD CHECK
if (state == 1 && checkPassword(parsedMessage)) {
password = parsedMessage;
return true;
}
if (state == 2) {
std::string type = std::get<0>(response);
//INFO
if( type == "I" ){
return true;
}
//PHOTO
if ( type == "F") {
return true;
}
}
return false;
}
/**
THIS FUNC WILL CHECK RESPONSE FROM THE ROBOT, AND DECIDE WHAT TO DO BASED ON THE STATE
@return tuple<bool TRUE if everything is right,std::string MESSAGE to send to the robot>
*/
std::tuple<bool,std::string> checkResponse(std::tuple<std::string, std::string> response){
if (state == 0) {
if (checkMessage(response)) {
std::cout << state << " / / state" << std::endl;
return std::make_tuple(true, "201 PASSWORDrn");
}
}
if (state == 1) {
// TADY BUDE JESTE PODMINKA, ZE HESLO JE SPRAVNE
if(checkMessage(response)){
std::cout << state << " / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / state" << std::endl;
return std::make_tuple(false, "500 LOGIN FAILEDrn");
}
}
if (state == 2) {
if (checkMessage(response)) {
std::cout << state << " / / / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / / / state" << std::endl;
return std::make_tuple(false, "501 SYNTAX ERROR rn");
}
}
std::cout << state << " / / / / / / / / state" << std::endl;
return std::make_tuple(false, "unexpected result");
}
/**
This func will parse the incoming buffer
@param buffer incoming buffer
@return tuple <String type of message (U,I,P,F), String actual message>
*/
std::tuple<std::string, std::string> parseBuffer(std::string buffer){
if (state == 0) {
return std::make_tuple("U", buffer);
}
if (state == 1) {
return std::make_tuple("P", buffer);
}else{
std::string delimeter = " ";
std::string::size_type pos = buffer.find(delimeter);
std::string type = buffer.substr(0, pos );
std::string message = buffer.erase(0, pos + delimeter.length());
return std::make_tuple(type, message);
}
}
int main(int argc, char *argv)
{
char buf[BUFFSIZE];
std::vector<std::string> outBuffer;
std::vector<std::string> inBuffer;
int sockfd, c_sockfd;
sockaddr_in my_addr, rem_addr;
socklen_t rem_addr_length;
int mlen;
const int PORT_NUM = atoi(argv[1]);
if( (PORT_NUM > MAX_PORT) || (PORT_NUM < MIN_PORT)){
perror("Port number is not acceptable");
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("Socket nelze otevrit");
exit(-1);
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT_NUM);
std::cout << PORT_NUM << " PORT NUM" << std::endl;
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
perror("Chyba v bind");
close(sockfd); exit(1);
}
if (listen(sockfd, SOMAXCONN) == -1)
{
perror("Nelze provest listen");
close(sockfd); exit(1);
}
while (1)
{
rem_addr_length=sizeof(rem_addr);
c_sockfd = accept(sockfd, (struct sockaddr*) &rem_addr, &rem_addr_length);
if ( c_sockfd == -1)
{
perror("Nelze accept");
close(sockfd); exit(1);
}
///FIRST MESSAGE
std::string ok = "200 LOGINrn";
send(c_sockfd, &ok, sizeof(std::string), 0);
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
perror("Chyba pri cteni");
else{
while (mlen)
{
///---------- MAIN PART--------------
//This is where comunication is happening
inBuffer.push_back(buf);
//Parse the buffer, check the message and
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
///---------- MAIN PART--------------
state++;
std::cout << state << " state num" << std::endl;
if (send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0) == -1)
{
perror("Chyba pri zapisu");
break;
}else{
}
std::cout << inBuffer.back() << std::endl;
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
{
perror("Chyba pri cteni");
break;
}
}
close(c_sockfd);
}
}
}
c++ sockets c++11 tcp telnet
I think I am missing something and doesn't make sense.
I am writing pretty simple TCP server, everything works pretty much as expected, but when a message saying "500 LOGIN FAILED" gets send over network, it get interpreted as "$500 LOGIN FAILED".
I am testing my server using telnet on localhost
here is simplified version of my code
recv(c_sockfd, buf, BUFFSIZE, 0))
inBuffer.push_back(buf);
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
in the checkResponse func, I am implementing logic to decide what message to send, and somehow when I send ERROR message the extra character is added at the beginning of the message.
EXAMPLE 1:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
674rn
202 OK
INFO iasdijasdjiajsdiajdijasidjiansdjsdvhdf dfvsdfsdfrn
&501 SYNTAX ERROR
Notice the "&" character
EXAMPLE 2:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345rn
201 PASSWORD
456rn
$500 LOGIN FAILED
Notice the "$" character
Does anyone have any idea where the extra characters could be added to the string?
I didn't want to include full code, because the requirement was to have all in one file, which makes it difficult to read. Here it goes tho.
FULL CODE:
#include <iostream>
#include <regex>
#include <iterator>
#include <vector>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <tuple>
#define MIN_PORT 3000
#define MAX_PORT 3999
#define BUFFSIZE 1000
/**
0 - LOGIN SUCCESSFUL, USERNAME IS IN THE BUFFER
1 - PASSWORD CHECK
2 - PASSWORD OK, COMMUNICATING
*/
int state = 0;
std::string username, password;
/**
CHECKS ENTERED PASSWORD BASES ON THE SUM OF ASCII VALUES OF USERNAME
@return: true on success, false otherwise
*/
bool checkPassword(std::string password){
std::istringstream sst;
sst.str(username);
unsigned char byte = '';
int value = 0;
// std::cout << "byte poprve: " << byte << std::endl;
// std::cout << "byte poprve INT: " << (int) byte << std::endl;
while (sst >> byte) {
std::cout << "podruhe: " << byte << std::endl;
std::cout << "podruhe INT: " << (int) byte << std::endl;
std::cout << "Prubezna SUMA: " << (int) value << std::endl;
value += byte;
}
std::cout << "suma: " << value << std::endl;
// Check the entered password
if (password == std::to_string(value)) {
return true;
}
return false;
}
/**
CHECKS MESSAGE SYNTAX BASED ON THE STATE WE ARE IN
CHECKS PASSWORD
CHECKS CHECK SUM
@param response <string type (if available), string message to parse>
@return TRUE on success, FALSE otherwise
*/
bool checkMessage(std::tuple<std::string,std::string> response){
auto messageToParse = std::get<1>(response);
std::string delimeter = "rn";
std::string::size_type pos = messageToParse.find(delimeter);
//INITIAL CHECK
if (pos < 1){
return false;
}
//somehow you have to multiply the length by 2
auto parsedMessage = messageToParse.substr(0,pos - 2*delimeter.length());
std::cout << parsedMessage << " : THIS IS YOUR PARSED MESSAGE";
//USERNAME
if (state == 0) {
username = parsedMessage;
return true;
}
//PASSWORD CHECK
if (state == 1 && checkPassword(parsedMessage)) {
password = parsedMessage;
return true;
}
if (state == 2) {
std::string type = std::get<0>(response);
//INFO
if( type == "I" ){
return true;
}
//PHOTO
if ( type == "F") {
return true;
}
}
return false;
}
/**
THIS FUNC WILL CHECK RESPONSE FROM THE ROBOT, AND DECIDE WHAT TO DO BASED ON THE STATE
@return tuple<bool TRUE if everything is right,std::string MESSAGE to send to the robot>
*/
std::tuple<bool,std::string> checkResponse(std::tuple<std::string, std::string> response){
if (state == 0) {
if (checkMessage(response)) {
std::cout << state << " / / state" << std::endl;
return std::make_tuple(true, "201 PASSWORDrn");
}
}
if (state == 1) {
// TADY BUDE JESTE PODMINKA, ZE HESLO JE SPRAVNE
if(checkMessage(response)){
std::cout << state << " / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / state" << std::endl;
return std::make_tuple(false, "500 LOGIN FAILEDrn");
}
}
if (state == 2) {
if (checkMessage(response)) {
std::cout << state << " / / / / / state" << std::endl;
return std::make_tuple(true, "202 OKrn");
}else{
std::cout << state << " / / / / / / state" << std::endl;
return std::make_tuple(false, "501 SYNTAX ERROR rn");
}
}
std::cout << state << " / / / / / / / / state" << std::endl;
return std::make_tuple(false, "unexpected result");
}
/**
This func will parse the incoming buffer
@param buffer incoming buffer
@return tuple <String type of message (U,I,P,F), String actual message>
*/
std::tuple<std::string, std::string> parseBuffer(std::string buffer){
if (state == 0) {
return std::make_tuple("U", buffer);
}
if (state == 1) {
return std::make_tuple("P", buffer);
}else{
std::string delimeter = " ";
std::string::size_type pos = buffer.find(delimeter);
std::string type = buffer.substr(0, pos );
std::string message = buffer.erase(0, pos + delimeter.length());
return std::make_tuple(type, message);
}
}
int main(int argc, char *argv)
{
char buf[BUFFSIZE];
std::vector<std::string> outBuffer;
std::vector<std::string> inBuffer;
int sockfd, c_sockfd;
sockaddr_in my_addr, rem_addr;
socklen_t rem_addr_length;
int mlen;
const int PORT_NUM = atoi(argv[1]);
if( (PORT_NUM > MAX_PORT) || (PORT_NUM < MIN_PORT)){
perror("Port number is not acceptable");
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("Socket nelze otevrit");
exit(-1);
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT_NUM);
std::cout << PORT_NUM << " PORT NUM" << std::endl;
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
perror("Chyba v bind");
close(sockfd); exit(1);
}
if (listen(sockfd, SOMAXCONN) == -1)
{
perror("Nelze provest listen");
close(sockfd); exit(1);
}
while (1)
{
rem_addr_length=sizeof(rem_addr);
c_sockfd = accept(sockfd, (struct sockaddr*) &rem_addr, &rem_addr_length);
if ( c_sockfd == -1)
{
perror("Nelze accept");
close(sockfd); exit(1);
}
///FIRST MESSAGE
std::string ok = "200 LOGINrn";
send(c_sockfd, &ok, sizeof(std::string), 0);
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
perror("Chyba pri cteni");
else{
while (mlen)
{
///---------- MAIN PART--------------
//This is where comunication is happening
inBuffer.push_back(buf);
//Parse the buffer, check the message and
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
///---------- MAIN PART--------------
state++;
std::cout << state << " state num" << std::endl;
if (send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0) == -1)
{
perror("Chyba pri zapisu");
break;
}else{
}
std::cout << inBuffer.back() << std::endl;
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
{
perror("Chyba pri cteni");
break;
}
}
close(c_sockfd);
}
}
}
c++ sockets c++11 tcp telnet
c++ sockets c++11 tcp telnet
edited Nov 12 '18 at 11:03
Yevgen Ponomarenko
asked Nov 12 '18 at 10:18
Yevgen PonomarenkoYevgen Ponomarenko
214
214
1
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
2
What isoutBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.
– Some programmer dude
Nov 12 '18 at 10:20
My spidey-sense indicates thatoutBuffer
andinBuffer
are collections ofstd::string
.
– molbdnilo
Nov 12 '18 at 10:36
You're aware that TCP is a streaming protocol, and that you can receive any amount of data withrecv
, right?
– molbdnilo
Nov 12 '18 at 10:38
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40
|
show 1 more comment
1
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
2
What isoutBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.
– Some programmer dude
Nov 12 '18 at 10:20
My spidey-sense indicates thatoutBuffer
andinBuffer
are collections ofstd::string
.
– molbdnilo
Nov 12 '18 at 10:36
You're aware that TCP is a streaming protocol, and that you can receive any amount of data withrecv
, right?
– molbdnilo
Nov 12 '18 at 10:38
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40
1
1
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
2
2
What is
outBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.– Some programmer dude
Nov 12 '18 at 10:20
What is
outBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.– Some programmer dude
Nov 12 '18 at 10:20
My spidey-sense indicates that
outBuffer
and inBuffer
are collections of std::string
.– molbdnilo
Nov 12 '18 at 10:36
My spidey-sense indicates that
outBuffer
and inBuffer
are collections of std::string
.– molbdnilo
Nov 12 '18 at 10:36
You're aware that TCP is a streaming protocol, and that you can receive any amount of data with
recv
, right?– molbdnilo
Nov 12 '18 at 10:38
You're aware that TCP is a streaming protocol, and that you can receive any amount of data with
recv
, right?– molbdnilo
Nov 12 '18 at 10:38
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40
|
show 1 more comment
1 Answer
1
active
oldest
votes
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string
objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string
is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string
object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string
object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53260039%2ftcp-server-message-extra-characters-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string
objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string
is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string
object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string
object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
add a comment |
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string
objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string
is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string
object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string
object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
add a comment |
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string
objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string
is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string
object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string
object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string
objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string
is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string
object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string
object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.
answered Nov 12 '18 at 11:18
Some programmer dudeSome programmer dude
295k24249411
295k24249411
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
add a comment |
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
I thought that I might run into some errors using std::string, thanks for the reply.
– Yevgen Ponomarenko
Nov 12 '18 at 12:22
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53260039%2ftcp-server-message-extra-characters-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
What's the code you are actually running? This is not a reproducible example.
– Matthieu Brucher
Nov 12 '18 at 10:20
2
What is
outBuffer
? Please try to create a Minimal, Complete, and Verifiable Example to show us.– Some programmer dude
Nov 12 '18 at 10:20
My spidey-sense indicates that
outBuffer
andinBuffer
are collections ofstd::string
.– molbdnilo
Nov 12 '18 at 10:36
You're aware that TCP is a streaming protocol, and that you can receive any amount of data with
recv
, right?– molbdnilo
Nov 12 '18 at 10:38
You never check the return values of your functions to see how many bytes arrived, you just use the whole buffer regardless. And you never check for errors.
– Galik
Nov 12 '18 at 10:40