通过 Socket C++ 发送长字符串 [英] Sending a long String over a Socket C++

查看:61
本文介绍了通过 Socket C++ 发送长字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用套接字进行一些基本的客户端 <-> 服务器通信时遇到了一个奇怪的问题.

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

服务器通过使用 ostringstream 对象和一些带有换行符和空格的简单格式将数据转储到一个长字符串中来打包包含玩家信息的结构数组,然后通过套接字将该字符串发送到客户端显示给玩家.

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.

当被打包的一个或多个结构体中的name"字段超过4个字符时,就会出现问题;如果是这种情况,则每个包含 5 个以上字符的名称"字段中第 4 个之后的每个字符都在发送到客户端的字符串 AFTER* 末尾的一行中重复.

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.

服务器代码:

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;
}

客户代码:

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(); 

屏幕截图,突出显示的相关部分:

有错误的截图

没有错误的截图

除非我遗漏了其他东西,否则我 99% 确定错误出在客户端的 do-while 接收循环中,因为字符串在服务器端打印时正确显示.出于对我的热爱,我无法想象会导致这种特定错误的原因,因为它只是发送了一个长字符串.

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.

推荐答案

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

这是错误的.缓冲区仅包含 bytes_recv 价值的接收数据.

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.

此外,

if (bytes_sent != leader_board_package.length())

这也是错误的.不要依赖 send 能够一次发送整个数组.正确的发送方式是像循环接收一样循环.

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.

目前还不清楚您的消息的大小应该是多少.如果它是可变的,则需要将其与消息一起传输.如果是 MAX_BUFF_LENGTH,则需要 send() 这个确切的字节数.您不能依赖通过 TCP 一次性发送或接收的消息.

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.

这篇关于通过 Socket C++ 发送长字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆