0

I'm having a strange issue with some basic client <-> server communication using sockets.

The server packages an array of structs containing player information by dumping the data into one long string using an ostringstream object and some some simple formatting with newlines and spaces, then sends that string via socket to the client to be displayed to the player.

The issue arises when the "name" field in the one or more of the structs being packaged is longer than 4 characters; if this is the case every character after the 4th from each "name" field containing 5+ characters is duplicated on a single line at the end of the string AFTER* being sent to the client.

*The packaged string always displays properly on the server side.

Below is the relevant code and two screenshots of server and client terminal, one displaying the error, the other without.

SERVER CODE:

struct leader_board_pos
{
    string name;
    int score;
};

leader_board_pos leader_board[num_players]; 

....

// Package and send the current leaderboard to the client 
int i = 0;
string leader_board_package;
string dubspace = "  ";
ostringstream oss;

cout << "Package leader board > "; cin.ignore();

leader_board_package = "Leader Board: \n";
while(i < num_leaders)
{
    oss << leader_board[i].name << dubspace << leader_board[i].score << endl;
    leader_board_package += oss.str();
    oss.str(string());
    i++;
}

cout << leader_board_package; cin.ignore();

bytes_sent = send(clientSock, leader_board_package.c_str(), leader_board_package.length(), 0);

if (bytes_sent != leader_board_package.length())
{
    cout << "Server Message: Communication error..." << endl;
    return;
}

CLIENT CODE:

const int MAX_BUFF_LENGTH = 4096;

...

//Get and display Leaderboard
int bytes_recv = 0;
vector<char> leader_board_buffer(MAX_BUFF_LENGTH);
string leader_board_package;

do {

    bytes_recv = recv(sock, leader_board_buffer.data(), MAX_BUFF_LENGTH, 0);

    if (bytes_recv == -1)
    {
        cout << "Communication error...";
        return 0;
    }
    else
    {
        leader_board_package.append(leader_board_buffer.begin(), leader_board_buffer.end());
    }

} while (bytes_recv == MAX_BUFF_LENGTH);

cout << endl << endl << leader_board_package; cin.ignore(); 

The Screenshots, Relevant sections highlighted:

Screenshot with Error

Screenshot without Error

Unless I'm missing something else I'm 99% sure the error is in the do-while receive loop on the client-side since the string displays appropriately when printed on the server-side. I can't for the love of me imagine what would cause such a specific error since it's just one long string being sent.

user3776749
  • 667
  • 1
  • 10
  • 20
  • Have you tried by disabling structure padding. Because there will be issue if structure padding is done internally by compiler. Since string is properly displayed in server side but issue is occouring in client side. One more thing since ostringstream you are using please check buffer clear and any issue related to that. – sagar Jun 03 '16 at 05:37
  • Your receive loop is not right. You have to add up `bytes_recv`, not replace it each iteration. Like `bytes_recv += recv(..` or better with an intermediate variable, so you can check it against `-1` each time. And the `while` condition then should be `!= MAX_BUFF_LENGTH`, not `==`. But you do not send `MAX_BUFF_LENGTH` bytes, so maybe you want to send a header first with the message length, so the client knows how much to receive. – Karsten Koop Jun 03 '16 at 06:54

1 Answers1

1
leader_board_package.append(leader_board_buffer.begin(), leader_board_buffer.end());

This is wrong. The buffer only contains bytes_recv worth of received data.

while (bytes_recv == MAX_BUFF_LENGTH);

If you assemble the message from pieces, you need to add their lengths together somewhere.

In addition,

if (bytes_sent != leader_board_package.length())

This is wrong too. Don't rely on send being able to send the entire array at once. The right way to send is to loop much in the same way you loop receiving.

It is also unclear what's the size of your message is supposed to be. If it's variable, you need to transmit it with the message. If it's MAX_BUFF_LENGTH, you need to send() this exact number of bytes. You cannot rely on a message being sent or received in one piece over TCP.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243