套接字通信数据在写入/读取时损坏 我有一个C++服务器,它与多个客户端通信。它使用一个向量来存储这些客户端(下面代码中的PlayerSocket)套接字的句柄。在“游戏”结束时,我希望服务器通过该向量循环,并向每个客户机写入相同的字符串。但是,有时客户端读取(然后显示)的数据会“损坏”,正如您在屏幕截图中所看到的,但第一个客户端不会发生这种情况,只有第二个客户端。我不明白为什么会这样!我在程序的早期使用了相同的技术(循环和编写),在这种情况下它总是很好地工作

套接字通信数据在写入/读取时损坏 我有一个C++服务器,它与多个客户端通信。它使用一个向量来存储这些客户端(下面代码中的PlayerSocket)套接字的句柄。在“游戏”结束时,我希望服务器通过该向量循环,并向每个客户机写入相同的字符串。但是,有时客户端读取(然后显示)的数据会“损坏”,正如您在屏幕截图中所看到的,但第一个客户端不会发生这种情况,只有第二个客户端。我不明白为什么会这样!我在程序的早期使用了相同的技术(循环和编写),在这种情况下它总是很好地工作,c++,linux,sockets,C++,Linux,Sockets,下面是应该显示的内容: 以下是我得到的: 以下是写入以下内容的服务器代码: std::string announcement = ""; if (playerWon) { ... } } else { announcement = "?No one won the game!\nGAME BOARD: " + cn.getGameBoard(); for (int player : gameData->playerSockets) { w

下面是应该显示的内容:

以下是我得到的:

以下是写入以下内容的服务器代码:

std::string announcement = "";
if (playerWon) {
    ...
    }
} else {
    announcement = "?No one won the game!\nGAME BOARD: " + cn.getGameBoard();
    for (int player : gameData->playerSockets) {
        write(player, announcement.c_str(), announcement.size() + 1);
    }
}
这是读取的客户端代码。请记住,有多个客户端正在运行并连接到服务器,并且此问题仅发生在服务器循环中第一个客户端以外的客户端上:

    static bool readMyTurn(int clientSd) {
        ...
        char buf[BUFSIZE];
        read(clientSd, buf, BUFSIZE);

        string myTurn(buf);
        cout << "MYMYMYMY: " << myTurn << endl;
        myTurn.erase(0, 1);
        cout << myTurn << endl;
        ...
    }
static bool readMyTurn(int-clientSd){
...
字符buf[BUFSIZE];
读取(clientSd、buf、BUFSIZE);
字符串myTurn(buf);

如果没有一个,我们不能远程诊断这个问题,但是我可以马上告诉你,你应该检查
读取
调用的结果……看起来你希望服务器端有一个
写入
调用,与客户端的一个
读取
调用关联。这不是一个合理的假设。TCP/IP是一种流协议…您是否在使用网络编程方面的书籍作为参考?
write()
read()
在TCP中发送/接收任意数量的字节。不能保证1
write()
将发送整个字符串,或者1
read()
将接收整个字符串。请注意它们的返回值!需要在循环中调用它们,以确保所有数据都已实际发送/received@TedLyngmo抱歉,制表符完成失败。@TEDLYNMO是的,说得好!我也实现了。非常感谢您的帮助!
string readOneStringFromServer(int clientSd, string &leftovers) {
ssize_t nullTerminatorPosition = 0;
std::string stringToReturn = "";

do {
    char buf[BUFSIZE];
    ssize_t bytesRead = read(clientSd, buf, BUFSIZE);
    nullTerminatorPosition = findPositionOfNullTerminator(buf, bytesRead);

    // found a null terminator
    if (nullTerminatorPosition != -1) {
        // create a buffer to hold all of the chars from buf1 up to and including the null terminator
        char upToNullTerminator[nullTerminatorPosition + 1];

        // get those chars from buf1 and put them into buf2 (including the null terminator)
        for (int i = 0; i < nullTerminatorPosition + 1; ++i) {
            upToNullTerminator[i] = buf[i];
        }

        // use buf2 to create a string
        stringToReturn += upToNullTerminator;

        // check if there are leftover bytes after the null terminator
        int leftoverBytes = bytesRead - nullTerminatorPosition - 1;
        if (leftoverBytes != 0) {
            // if there are, create a char array of that size
            char leftoverChars[leftoverBytes];

            // loop through buf1 and add the leftover chars to buf3
            for (int i = nullTerminatorPosition + 1; i < bytesRead; ++i) {
                leftoverChars[i - (nullTerminatorPosition + 1)] = buf[i];
            }

            // make a string out of those leftover chars
            leftovers = leftoverChars;
        } else {
            // if there are no leftover bytes, then we want to "erase" what is currently held in leftovers so that
            // it doesn't get passed to the next function call
            leftovers = "";
        }
    // didn't find one
    } else {
        stringToReturn += buf;
    }

} while (nullTerminatorPosition == -1);

return stringToReturn;
}