简体   繁体   English

如何在 C++ 中的套接字上写多行

[英]How to write multiple lines over a socket in c++

quite new to socket programming and just had a short question, i'm trying to display multiple lines of output on my client from the server but I can't seem to get the lines to separate.对套接字编程非常陌生,只是有一个简短的问题,我试图在我的客户端上从服务器显示多行输出,但我似乎无法将这些行分开。 Any help appreciated.任何帮助表示赞赏。

Server:服务器:

void help(int sock)
{
    n = write(sock,"Commands:\n",11);
    n = write(sock,"HELP -> Displays usable commands\n",34);
    n = write(sock,"BROADCAST 'message' -> Sends 'message' to every user\n",54);
    n = write(sock,"SEND 'user' 'message' -> Sends 'message' to 'user'\n",52);
    n = write(sock,"DISPLAY -> Displays all current users\n",39);
    n = write(sock,"LEAVE -> Ends the current session\n",35);
}

Client:客户:

while(buffer[0] != 'L')
    {
        bzero(buffer,256);
        n = read(sockfd,buffer,255);
        cout << buffer << "\n";
    }

There are three issues with your code:您的代码存在三个问题:

  1. your calls to write() are including the null terminators of the strings.您对write()调用包括字符串的空终止符。 You should not be that in this situation.在这种情况下,你不应该那样。

  2. your read() code is ignoring the return value of read() .您的read()代码忽略了read()的返回值。 Just because you ask for 255 bytes does not guarantee that you will receive 255 bytes.仅仅因为您要求 255 个字节并不能保证您将收到 255 个字节。 The return value tells you how many bytes were actually received.返回值告诉您实际接收了多少字节。 And the bytes that you do receive are not guaranteed to be null terminated, either, so you can't write the buffer as a plain char* pointer alone to std::cout , that will make it look for a null terminator.并且您收到的字节也不能保证以空终止,因此您不能将缓冲区作为一个普通的char*指针单独写入std::cout ,这将使其寻找空终止符。 std::cout has a write() method that you can use to specify how many char s are to be written. std::cout有一个write()方法,您可以使用它来指定要写入的char数量。 Use the return value of read() for that purpose.为此使用read()的返回值。

  3. aside from that, you are assuming that call to read() will read a single complete line, so that you can check the first char in the last received buffer for the L of the final LEAVE line.除此之外,您假设对read()调用将读取一个完整的行,以便您可以检查最后接收的缓冲区中的第一个char以获取最后一个LEAVE行的L That is simply not true, and you can't rely on that.这根本不是真的,你不能依赖它。 TCP is a byte stream, read() is going to receive and return arbitrary amounts of data, depending on what is available in the socket's receive buffer. TCP 是一个字节流, read()将接收和返回任意数量的数据,具体取决于套接字接收缓冲区中可用的数据。 If you need to read line-based data, you will have to accumulate the input bytes into a growing buffer of some kind and then scan that for line breaks as new data arrives.如果您需要读取基于行的数据,则必须将输入字节累积到某种不断增长的缓冲区中,然后在新数据到达时对其进行换行扫描。 You can then remove only completed lines from that buffer and process their content as needed.然后,您可以仅从该缓冲区中删除已完成的行并根据需要处理其内容。

Try something more like this instead:尝试更像这样的事情:

int writestr(int sock, const char *str)
{
    int n, len = strlen(str);
    while (len > 0)
    {
        n = write(sock, str, len);
        if (n < 0) return n;
        str += n;
        len -= n;
    }
    return 0;
}

void help(int sock)
{
    n = writestr(sock, "Commands:\n");
    n = writestr(sock, "HELP -> Displays usable commands\n");
    n = writestr(sock, "BROADCAST 'message' -> Sends 'message' to every user\n");
    n = writestr(sock, "SEND 'user' 'message' -> Sends 'message' to 'user'\n");
    n = writestr(sock, "DISPLAY -> Displays all current users\n");
    n = writestr(sock, "LEAVE -> Ends the current session\n");
}

char buffer[256];
std::string data;
std::string::size_type pos, last_pos = 0;

while (true)
{
    n = read(sockfd, buffer, sizeof(buffer));
    if (n <= 0) break;

    std::cout.write(buffer, n);

    data.append(buffer, n);

    pos = data.find('\n', last_pos);
    if (pos != std::string::npos)
    {
        std::string line = data.substr(0, pos);
        /* if you want to support CRLF line breaks, do this instead:
        std::string::size_type len = pos;
        if ((len > 0) && (data[len-1] == '\r'))
            --len;
        std::string line = data.substr(0, len);
        */

        data.erase(0, pos+1);

        if (line.compare(0, 5, "LEAVE") == 0)
            break;

        last_pos = 0;
    }
    else
        last_pos = data.size();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM