【问题标题】:recv() not getting all data sent by client using send()recv() 没有得到客户端使用 send() 发送的所有数据
【发布时间】:2018-02-17 23:46:25
【问题描述】:

我真的不知道这是否是网络、我的电脑或其他什么的某种延迟,我对套接字编程很陌生,并且一直试图让它工作一段时间,实现一个简单的框架来减轻我在班级未来项目中的工作,并在遇到的问题中使用这些功能:

void TCPSocket::send(const std::string& message, int flags) {

    if (isListening || !isConnected) {
        throw ConnectionException("Can't send message from a socket that is not connected");
    }

    int msgLength = message.length();
    int bytesLeft = msgLength;
    int bytesSent;
    const char* cMessage = message.c_str();

    while (bytesSent < msgLength) {

        const char* cMessageLeft = cMessage + bytesSent;

        int result = ::send(socketFd, cMessageLeft, bytesLeft, flags);
        if (result == -1) {
            throw ConnectionException("Could not send message. Error: " + std::string(strerror(errno)));
        }

        bytesLeft -= result;
        bytesSent += result;

    }

}

std::string TCPSocket::recv(unsigned int maxlen, int flags) {

    if (isListening || !isConnected) {
        throw ConnectionException("Can't receive message in a socket that is not connected");
    }

    char buffer[maxlen+1];
    int result = ::recv(socketFd, buffer, maxlen, flags);

    if (result == -1) {
        throw ConnectionException("Could not receive message. Error: " + std::string(strerror(errno)));
    }
    if (result ==  0) {
        isConnected = false;
        throw ClosedConnection("Client closed connection.");
    }
    buffer[result] = '\0';
    std::string message(buffer);

    return message;

}

它只适用于一条消息,我使用不同的可执行文件接收和发送完全没有问题,但我尝试发送超过 1 条消息并且我的问题开始了,有时我让服务器接收 1 条消息,有时它什么都没有,当我只添加几个 printf()s 时,它会全部接收,有人可以向我解释为什么会发生这种情况吗?

客户端代码:

int main() {
    TCPSocket cl1(0);

    try {
        cl1.connect("localhost", 1170);
        for (int i = 0; i < 5; i++) {
            //printf("Esperando 5s... ");
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            //printf("Pronto!\n\n");

            cl1.send("Thank you!\n");
            //printf("Msg enviada\n\n");

        }
        cl1.close();
    }
    catch( std::exception &e) {
        std::cout << e.what() << std::endl;
    }
}

服务器代码:

int main() {
    TCPSocket sv1(0);

    try {
        sv1.bind(1170);
        sv1.listen();
        TCPSocket client = sv1.accept();
        printf("Cliente conectado\n");
        try {
            for (;;) {
                //client.send("Welcome !\n");
                std::cout << client.recv(256) << std::endl;
            }
        }
        catch (const ClosedConnection & x) {
            printf("Connection closed\n");
        }

    }
    catch( std::exception &e) {
        std::cout << e.what() << std::endl;
    }
}

如果我取消注释客户端代码上的 printfs,所有数据都会在服务器上接收。

澄清一下,我以 5 秒的间隔发送消息,但 recv() 仍然只读取第一个消息并阻塞,直到 client 完成它的执行,从不读取应该在缓冲区中的其余消息。出于某种原因,在客户端代码上使用 printfs 会使应用程序运行良好。

【问题讨论】:

  • 按设计。 TCP是流协议,不是消息协议。换句话说,您需要循环调用recv,直到收到您期望的所有数据。
  • @selbie 我明白这一点,但是为什么我只收到一次“谢谢”,而我已经发送了 5 次并且它们应该在缓冲区中?如果我非常快地发送 5 次,那么 recv() 会将它们全部返回到同一个字符串中,但这不是正在发生的事情。
  • int bytesSent;
  • @MikaelMello 您关于添加打印语句改变行为的评论对我来说是一个赠品——将其范围缩小到几件事:时间问题、输出缓冲区刷新问题或内存布局更改问题。原来是后者。

标签: c++ sockets network-programming send recv


【解决方案1】:

您似乎没有初始化bytesSent,因此它实际发送数据的次数似乎不确定。

    int bytesSent = 0;

【讨论】:

  • 显然这确实是问题所在,我现在觉得很愚蠢,谢谢。
  • 感到愚蠢对你有好处。或者至少这对你来说比感觉聪明和愚蠢要好。
猜你喜欢
  • 2017-08-17
  • 2013-03-14
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 2017-10-17
相关资源
最近更新 更多