如何使用C++

发布于 2025-02-01 18:34:54 字数 2588 浏览 3 评论 0原文

我是TCP客户端/服务器通信的新手。我正在尝试将输出发送在服务器中的循环中,并在客户端中接收它。

我的问题是,我在客户端中获得随机值。

我已经共享了我的服务器和客户端片段:

server.cpp

string r_n, r_n1, r_n2, r_n3, r_n4, r_n5, r_n6, r_n7, r_n8, r_n9;

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    r_n =  c[0].as<int>();
    r_n1 = c[1].as<string>();

    r_n2 = c[2].as<string>();
    r_n3 = c[3].as<string>();
    r_n4 = to_string(c[4].as<long long int>());
    r_n5 = c[5].as<string>();
    r_n6 = c[6].as<string>();
    r_n7 = c[7].as<string>();
    r_n8 = to_string(c[8].as<int>());
    r_n9 = to_string(c[9].as<int>());

    send(serverSocket, r_n.c_str(), sizeof(r_n), 0);
    send(serverSocket, r_n1.c_str(), sizeof(r_n1), 0);
    send(serverSocket, r_n2.c_str(), sizeof(r_n2), 0);
    send(serverSocket, r_n3.c_str(), sizeof(r_n3), 0);
    send(serverSocket, r_n4.c_str(), sizeof(r_n4), 0);
    send(serverSocket, r_n5.c_str(), sizeof(r_n5), 0);
    send(serverSocket, r_n6.c_str(), sizeof(r_n6), 0);
    send(serverSocket, r_n7.c_str(), sizeof(r_n7), 0);
    send(serverSocket, r_n8.c_str(), sizeof(r_n8), 0);
    send(serverSocket, r_n9.c_str(), sizeof(r_n9), 0);
}

client.cpp

int i = 0;
while (i < 4)
{
    recv(TCPClientSocket, RecvBuffer, sizeof(RecvBuffer), 0);
    recv(TCPClientSocket, RecvBuffer1, sizeof(RecvBuffer1), 0);
    recv(TCPClientSocket, RecvBuffer2, sizeof(RecvBuffer2), 0);
    recv(TCPClientSocket, RecvBuffer3, sizeof(RecvBuffer3), 0);
    recv(TCPClientSocket, RecvBuffer4, sizeof(RecvBuffer4), 0);
    recv(TCPClientSocket, RecvBuffer5, sizeof(RecvBuffer5), 0);
    recv(TCPClientSocket, RecvBuffer6, sizeof(RecvBuffer6), 0);
    recv(TCPClientSocket, RecvBuffer6, sizeof(RecvBuffer6), 0);
    recv(TCPClientSocket, RecvBuffer7, sizeof(RecvBuffer7), 0);
    recv(TCPClientSocket, RecvBuffer8, sizeof(RecvBuffer8), 0);
    recv(TCPClientSocket, RecvBuffer9, sizeof(RecvBuffer9), 0);

    cout << "\t" << RecvBuffer << "\t" << RecvBuffer1 << "\t" << RecvBuffer2 << "\t" << RecvBuffer3;
    cout << "\t" << RecvBuffer4 << "\t" << RecvBuffer5 << "\t" << RecvBuffer6 << "\t" << RecvBuffer7 << "\t" << RecvBuffer8 << "\t" << RecvBuffer9 << endl;
    cout << endl;

    i++;
}

在客户端输出:

102     AC      First   shek 9944833930      Chennai      2022-05-21      6       1000

I am new to TCP client/server communication. I am trying to send output in a loop in the server and to receive it in the client.

My problem is, I am getting random values as output in the client.

I have shared my server and client snippets:

server.cpp

string r_n, r_n1, r_n2, r_n3, r_n4, r_n5, r_n6, r_n7, r_n8, r_n9;

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    r_n =  c[0].as<int>();
    r_n1 = c[1].as<string>();

    r_n2 = c[2].as<string>();
    r_n3 = c[3].as<string>();
    r_n4 = to_string(c[4].as<long long int>());
    r_n5 = c[5].as<string>();
    r_n6 = c[6].as<string>();
    r_n7 = c[7].as<string>();
    r_n8 = to_string(c[8].as<int>());
    r_n9 = to_string(c[9].as<int>());

    send(serverSocket, r_n.c_str(), sizeof(r_n), 0);
    send(serverSocket, r_n1.c_str(), sizeof(r_n1), 0);
    send(serverSocket, r_n2.c_str(), sizeof(r_n2), 0);
    send(serverSocket, r_n3.c_str(), sizeof(r_n3), 0);
    send(serverSocket, r_n4.c_str(), sizeof(r_n4), 0);
    send(serverSocket, r_n5.c_str(), sizeof(r_n5), 0);
    send(serverSocket, r_n6.c_str(), sizeof(r_n6), 0);
    send(serverSocket, r_n7.c_str(), sizeof(r_n7), 0);
    send(serverSocket, r_n8.c_str(), sizeof(r_n8), 0);
    send(serverSocket, r_n9.c_str(), sizeof(r_n9), 0);
}

client.cpp

int i = 0;
while (i < 4)
{
    recv(TCPClientSocket, RecvBuffer, sizeof(RecvBuffer), 0);
    recv(TCPClientSocket, RecvBuffer1, sizeof(RecvBuffer1), 0);
    recv(TCPClientSocket, RecvBuffer2, sizeof(RecvBuffer2), 0);
    recv(TCPClientSocket, RecvBuffer3, sizeof(RecvBuffer3), 0);
    recv(TCPClientSocket, RecvBuffer4, sizeof(RecvBuffer4), 0);
    recv(TCPClientSocket, RecvBuffer5, sizeof(RecvBuffer5), 0);
    recv(TCPClientSocket, RecvBuffer6, sizeof(RecvBuffer6), 0);
    recv(TCPClientSocket, RecvBuffer6, sizeof(RecvBuffer6), 0);
    recv(TCPClientSocket, RecvBuffer7, sizeof(RecvBuffer7), 0);
    recv(TCPClientSocket, RecvBuffer8, sizeof(RecvBuffer8), 0);
    recv(TCPClientSocket, RecvBuffer9, sizeof(RecvBuffer9), 0);

    cout << "\t" << RecvBuffer << "\t" << RecvBuffer1 << "\t" << RecvBuffer2 << "\t" << RecvBuffer3;
    cout << "\t" << RecvBuffer4 << "\t" << RecvBuffer5 << "\t" << RecvBuffer6 << "\t" << RecvBuffer7 << "\t" << RecvBuffer8 << "\t" << RecvBuffer9 << endl;
    cout << endl;

    i++;
}

output in client:

102     AC      First   shek 9944833930      Chennai      2022-05-21      6       1000

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尴尬癌患者 2025-02-08 18:34:54

TCP是一个字节流,它没有消息边界的概念,因此您必须对数据本身中的数据尺寸明确说明。通过在发送数据本身之前发送数据的大小,或者通过在数据之后发送唯一的终结器。

您的字符串数据是可变长度。

在发送字符串通过发送() sizef()是错误的缓冲区大小。您需要改用字符串的size()方法。您还需要注意send()的返回值,因为它告诉您实际接受了多少个字节,可以是(和通常是)小于所请求的字节数。与recv()相同。因此,您需要在循环中调用两个功能,直到您发送/接收到预期的字节数为止。同样,来自recv()的输出不是终止的,但是您的代码期望它会成为。

话虽如此,请尝试使用更多类似的东西:

server.cpp

void sendRaw(int socket, const void *data, size_t size)
{
    const char *ptr = reinterpret_cast<const char*>(data); 
    while (size > 0)
    {
        int numSent = send(socket, ptr, size, 0);
        if (numSent < 0) throw ...;
        ptr += numSent;
        size -= numSent;
    }
}

void sendUInt32(int socket, uint32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendString(int socket, const string &str)
{
    uint32_t size = str.size();
    sendUInt32(socket, size);
    sendRaw(socket, str.c_str(), size);
}

...

string n_r[10];

sendUInt32(serverSocket, R.size());

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    n_r[0] = to_string(c[0].as<int>();
    n_r[1] = c[1].as<string>();
    n_r[2] = c[2].as<string>();
    n_r[3] = c[3].as<string>();
    n_r[4] = to_string(c[4].as<long long int>());
    n_r[5] = c[5].as<string>();
    n_r[6] = c[6].as<string>();
    n_r[7] = c[7].as<string>();
    n_r[8] = to_string(c[8].as<int>());
    n_r[9] = to_string(c[9].as<int>());

    for(int i = 0; i < 10; ++i) {
        sendString(serverSocket, n_r[i]);
    }
}

client.cpp

void recvRaw(int socket, void *data, size_t size)
{
    char *ptr = reinterpret_cast<char*>(data); 
    while (size > 0)
    {
        int numRecvd = recv(socket, ptr, size, 0);
        if (numRecvd <= 0) throw ...;
        ptr += numRecvd;
        size -= numRecvd;
    }
}

uint32_t recvUInt32(int socket)
{
    uint32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

string recvString(int socket)
{
    string str;
    uint32_t size = recvUInt32(socket);
    if (size > 0)
    {
        str.resize(size);
        recvRaw(socket, str.data(), size);
    }
    return str;
}

...

string r_n[10];
uint32_t count = recvUInt32(TCPClientSocket);

for(uint32_t i = 0; i < count; ++i)
{
    for (int i = 0; i < 10; ++i) {
        r_n[i] = recvString(TCPClientSocket);
    }

    for (int i = 0; i < 10; ++i) {
        cout << '\t' << r_n[i];
    }
    cout << endl << endl;
}

也是如此,您的某些输出字段最初是整数而不是字符串,因此最好将它们发送为整数而不是字符串,例如:

server.cpp

void sendRaw(int socket, const void *data, size_t size)
{
    const char *ptr = reinterpret_cast<const char*>(data); 
    while (size > 0)
    {
        int numSent = send(socket, ptr, size, 0);
        if (numSent < 0) throw ...;
        ptr += numSent;
        size -= numSent;
    }
}

void sendUInt32(int socket, uint32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendInt32(int socket, int32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendInt64(int socket, int64_t value)
{
    value = htonll(value); // or whatever equivalent your environment provides
    sendRaw(socket, &value, sizeof(value));
}

void sendString(int socket, const string &str)
{
    uint32_t size = str.size();
    sendUInt32(socket, size);
    sendRaw(socket, str.c_str(), size);
}

...

int n_r, n_r8, n_r9;
string n_r1, n_r2, n_r3, n_r5, n_r6, n_r7;
long long int n_r4;

sendUInt32(serverSocket, R.size());

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    n_r  = c[0].as<int>();
    n_r1 = c[1].as<string>();
    n_r2 = c[2].as<string>();
    n_r3 = c[3].as<string>();
    n_r4 = c[4].as<long long int>();
    n_r5 = c[5].as<string>();
    n_r6 = c[6].as<string>();
    n_r7 = c[7].as<string>();
    n_r8 = c[8].as<int>();
    n_r9 = c[9].as<int>();

    sendInt32(serverSocket, n_r);
    sendString(serverSocket, n_r1);
    sendString(serverSocket, n_r2);
    sendString(serverSocket, n_r3);
    sendInt64(serverSocket, n_r4);
    sendString(serverSocket, n_r5);
    sendString(serverSocket, n_r6);
    sendString(serverSocket, n_r7);
    sendInt32(serverSocket, n_r8);
    sendInt32(serverSocket, n_r9);
}

client.cpp

void recvRaw(int socket, void *data, size_t size)
{
    char *ptr = reinterpret_cast<char*>(data); 
    while (size > 0)
    {
        int numRecvd = recv(socket, ptr, size, 0);
        if (numRecvd <= 0) throw ...;
        ptr += numRecvd;
        size -= numRecvd;
    }
}

uint32_t recvUInt32(int socket)
{
    uint32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

int32_t recvInt32(int socket)
{
    int32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

int64_t recvInt64(int socket)
{
    int32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohll(value); // or whatever equivalent your environment provides
}

string recvString(int socket)
{
    string str;
    uint32_t size = recvUInt32(socket);
    if (size > 0)
    {
        str.resize(size);
        recvRaw(socket, str.data(), size);
    }
    return str;
}

...

int n_r, n_r8, n_r9;
string n_r1, n_r2, n_r3, n_r5, n_r6, n_r7;
long long int n_r4;

uint32_t count = recvUInt32(TCPClientSocket);

for(uint32_t i = 0; i < count; ++i)
{
    n_r  = recvInt32(TCPClientSocket);
    n_r1 = recvString(TCPClientSocket);
    n_r2 = recvString(TCPClientSocket);
    n_r3 = recvString(TCPClientSocket);
    n_r4 = recvInt64(TCPClientSocket);
    n_r5 = recvString(TCPClientSocket);
    n_r6 = recvString(TCPClientSocket);
    n_r7 = recvString(TCPClientSocket);
    n_r8 = recvInt32(TCPClientSocket);
    n_r9 = recvInt32(TCPClientSocket);

    cout << '\t' << n_r << '\t' << n_r1 << '\t' << n_r2 << '\t' << n_r3 << '\t' << n_r4 << '\t' << n_r5 << '\t' << n_r6 << '\t' << n_r7 << '\t' << n_r8 << '\t' << n_r9 << endl << endl;
}

TCP is a byte stream, it has no concept of message boundaries, so you have to be explicit about data sizes in the data itself. Either by sending the data's size before sending the data itself, or by sending a unique terminator after the data.

Your string data is variable-length, but you are not delimiting your strings in any way, so the client has no way to know how much data is actually being sent, or even which data belongs to which string.

When sending a string via send(), sizeof() is the wrong buffer size to use. You need to use the string's size() method instead. You also need to pay attention to send()'s return value, as it tells you how many bytes were actually accepted for sending, which may be (and frequently is) less than the number of bytes requested. Same with recv(). So, you need to call both functions in loops until you have sent/received the expected number of bytes. Also, the output from recv() is not null-terminated, but your code is expecting it to be.

With that said, try something more like this instead:

server.cpp

void sendRaw(int socket, const void *data, size_t size)
{
    const char *ptr = reinterpret_cast<const char*>(data); 
    while (size > 0)
    {
        int numSent = send(socket, ptr, size, 0);
        if (numSent < 0) throw ...;
        ptr += numSent;
        size -= numSent;
    }
}

void sendUInt32(int socket, uint32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendString(int socket, const string &str)
{
    uint32_t size = str.size();
    sendUInt32(socket, size);
    sendRaw(socket, str.c_str(), size);
}

...

string n_r[10];

sendUInt32(serverSocket, R.size());

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    n_r[0] = to_string(c[0].as<int>();
    n_r[1] = c[1].as<string>();
    n_r[2] = c[2].as<string>();
    n_r[3] = c[3].as<string>();
    n_r[4] = to_string(c[4].as<long long int>());
    n_r[5] = c[5].as<string>();
    n_r[6] = c[6].as<string>();
    n_r[7] = c[7].as<string>();
    n_r[8] = to_string(c[8].as<int>());
    n_r[9] = to_string(c[9].as<int>());

    for(int i = 0; i < 10; ++i) {
        sendString(serverSocket, n_r[i]);
    }
}

client.cpp

void recvRaw(int socket, void *data, size_t size)
{
    char *ptr = reinterpret_cast<char*>(data); 
    while (size > 0)
    {
        int numRecvd = recv(socket, ptr, size, 0);
        if (numRecvd <= 0) throw ...;
        ptr += numRecvd;
        size -= numRecvd;
    }
}

uint32_t recvUInt32(int socket)
{
    uint32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

string recvString(int socket)
{
    string str;
    uint32_t size = recvUInt32(socket);
    if (size > 0)
    {
        str.resize(size);
        recvRaw(socket, str.data(), size);
    }
    return str;
}

...

string r_n[10];
uint32_t count = recvUInt32(TCPClientSocket);

for(uint32_t i = 0; i < count; ++i)
{
    for (int i = 0; i < 10; ++i) {
        r_n[i] = recvString(TCPClientSocket);
    }

    for (int i = 0; i < 10; ++i) {
        cout << '\t' << r_n[i];
    }
    cout << endl << endl;
}

That being said, some of your output fields were originally integers and not strings, so it would be better to send them as integers and not as strings, eg:

server.cpp

void sendRaw(int socket, const void *data, size_t size)
{
    const char *ptr = reinterpret_cast<const char*>(data); 
    while (size > 0)
    {
        int numSent = send(socket, ptr, size, 0);
        if (numSent < 0) throw ...;
        ptr += numSent;
        size -= numSent;
    }
}

void sendUInt32(int socket, uint32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendInt32(int socket, int32_t value)
{
    value = htonl(value);
    sendRaw(socket, &value, sizeof(value));
}

void sendInt64(int socket, int64_t value)
{
    value = htonll(value); // or whatever equivalent your environment provides
    sendRaw(socket, &value, sizeof(value));
}

void sendString(int socket, const string &str)
{
    uint32_t size = str.size();
    sendUInt32(socket, size);
    sendRaw(socket, str.c_str(), size);
}

...

int n_r, n_r8, n_r9;
string n_r1, n_r2, n_r3, n_r5, n_r6, n_r7;
long long int n_r4;

sendUInt32(serverSocket, R.size());

for (result::const_iterator c = R.begin(); c != R.end(); ++c) {

    n_r  = c[0].as<int>();
    n_r1 = c[1].as<string>();
    n_r2 = c[2].as<string>();
    n_r3 = c[3].as<string>();
    n_r4 = c[4].as<long long int>();
    n_r5 = c[5].as<string>();
    n_r6 = c[6].as<string>();
    n_r7 = c[7].as<string>();
    n_r8 = c[8].as<int>();
    n_r9 = c[9].as<int>();

    sendInt32(serverSocket, n_r);
    sendString(serverSocket, n_r1);
    sendString(serverSocket, n_r2);
    sendString(serverSocket, n_r3);
    sendInt64(serverSocket, n_r4);
    sendString(serverSocket, n_r5);
    sendString(serverSocket, n_r6);
    sendString(serverSocket, n_r7);
    sendInt32(serverSocket, n_r8);
    sendInt32(serverSocket, n_r9);
}

client.cpp

void recvRaw(int socket, void *data, size_t size)
{
    char *ptr = reinterpret_cast<char*>(data); 
    while (size > 0)
    {
        int numRecvd = recv(socket, ptr, size, 0);
        if (numRecvd <= 0) throw ...;
        ptr += numRecvd;
        size -= numRecvd;
    }
}

uint32_t recvUInt32(int socket)
{
    uint32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

int32_t recvInt32(int socket)
{
    int32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohl(value);
}

int64_t recvInt64(int socket)
{
    int32_t value;
    recvRaw(socket, &value, sizeof(value));
    return ntohll(value); // or whatever equivalent your environment provides
}

string recvString(int socket)
{
    string str;
    uint32_t size = recvUInt32(socket);
    if (size > 0)
    {
        str.resize(size);
        recvRaw(socket, str.data(), size);
    }
    return str;
}

...

int n_r, n_r8, n_r9;
string n_r1, n_r2, n_r3, n_r5, n_r6, n_r7;
long long int n_r4;

uint32_t count = recvUInt32(TCPClientSocket);

for(uint32_t i = 0; i < count; ++i)
{
    n_r  = recvInt32(TCPClientSocket);
    n_r1 = recvString(TCPClientSocket);
    n_r2 = recvString(TCPClientSocket);
    n_r3 = recvString(TCPClientSocket);
    n_r4 = recvInt64(TCPClientSocket);
    n_r5 = recvString(TCPClientSocket);
    n_r6 = recvString(TCPClientSocket);
    n_r7 = recvString(TCPClientSocket);
    n_r8 = recvInt32(TCPClientSocket);
    n_r9 = recvInt32(TCPClientSocket);

    cout << '\t' << n_r << '\t' << n_r1 << '\t' << n_r2 << '\t' << n_r3 << '\t' << n_r4 << '\t' << n_r5 << '\t' << n_r6 << '\t' << n_r7 << '\t' << n_r8 << '\t' << n_r9 << endl << endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文