【问题标题】:Why recv() function in sockets does not return anything?为什么套接字中的 recv() 函数不返回任何内容?
【发布时间】:2020-04-15 06:33:50
【问题描述】:

我是套接字编程的初学者,我在 Eclipse 中使用 C++。程序成功执行,但服务器端的recv() 函数不返回任何内容。它一直在等待而不终止程序。

服务器程序的recv()函数:

void Server2::readSocket(){

    if(recv(newsockfd, buffer, sizeof(buffer), 0) < 0){
        int err = WSAGetLastError();
        cout << "Read failed with error " << err << endl;
        perror("Reading failed");
        exit(EXIT_FAILURE);
    }

    cout << "MESSAGE: " << buffer << endl;
}

客户端程序:

void Client2::clientSocket(){

    #ifdef WIN32
    // Initialize Winsock
    int iResult;
    WSADATA wsaData;
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        std::cout << "WSAStartup failed: " << iResult << std::endl;

    }
    #endif

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if(sockfd < 0){
        int err = WSAGetLastError();
        cout << "Client Socket failed with error " << err << endl;
        exit(EXIT_FAILURE);
    }

}

void Client2::clientBCopy(){

    server = gethostbyname("127.0.0.1");

    bzero((char *)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

    serv_addr.sin_port = htons(portno);

}

void Client2::clientConnect(){

    if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
        int err = WSAGetLastError();
        cout << "Client Connect failed with error " << err << endl;
        exit(EXIT_FAILURE);
    }

    cout << "Please enter message: ";
    bzero(buffer, 256);
    fgets(buffer, 255, stdin);

}

void Client2::clientWrite(){

    if(write(sockfd, buffer, strlen(buffer)) < 0){
        int err = WSAGetLastError();
        cout << "Client Write failed with error " << err << endl;
        perror("Write Failed");
        exit(EXIT_FAILURE);
    }

    bzero(buffer, 256);
}

void Client2::clientRead(){

    if(recv(sockfd, buffer, 255, 0) < 0){
        int err = WSAGetLastError();
        cout << "Client Read failed with error " << err << endl;
        exit(EXIT_FAILURE);
    }
}

我该如何解决这个问题? 如果这还不够,请让我提供其余代码,感谢您的帮助!

【问题讨论】:

  • recv 一直阻塞,直到数据到达给定的套接字。从您的问题的上下文来看,尚不清楚a)数据甚至由客户端发送,以便服务器可以接收它们,并且b)这是负责与客户端连接的正确套接字。因此,a) 或 b) 都可能是问题所在,但由于您的问题缺乏上下文,因此不知道其中哪一个(或两者)。我建议您create a Minimal, Reproducible Example 以便提供其他人需要的所有信息来帮助您。
  • 有很多可能的原因。请在问题中添加这是什么类型的套接字(TCP、UDP,对我们这些人来说完全出乎意料吗?),它是如何配置的(可能需要minimal reproducible example 来了解所有细微差别),以及您的情况如何向此套接字发送消息。
  • 我也可以发布客户端程序吗? @SteffenUllrich
  • 哦!这是一个 tcp 套接字
  • 旁注:记住 TCP 是一个流,调用 recv 可以给你看似随机的数据量。不要假设您得到的内容很好地以 null 结尾并且可以使用 &lt;&lt; 安全打印。

标签: c++ windows eclipse sockets


【解决方案1】:

据我了解

recv() 函数应返回写入缓冲区参数指向的缓冲区的消息长度。

int fd_set_blocking(int fd, int blocking) {
/* Save the current flags */
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1)
    return 0;

if (blocking)`enter code here`
    flags &= ~O_NONBLOCK;
else
    flags |= O_NONBLOCK;
return fcntl(fd, F_SETFL, flags) != -1;

}

如果套接字上没有可用的消息,并且在套接字的文件描述符上没有设置 O_NONBLOCK,则 recv() 将阻塞,直到消息到达。可能是缓冲区没有正确复制到文件描述符中。

感谢和问候, Gunasekaran J

【讨论】:

  • 如何将 O_NONBLOCK 设置为套接字的文件描述符?
  • @ManujayaPremathilaka 你可能不想那样做。大多数情况下,非阻塞套接字用于轮询套接字以获取数据。如果套接字配置错误并且无法接收数据或只是没有接收数据,这将无济于事。在您弄清楚为什么 recv 没有收到并且之后可能不会收到之前,这是您不想要的复杂情况。
【解决方案2】:

终于,我发现了我的错误。

    cout << "Please enter message: ";
    bzero(buffer, 256);
    fgets(buffer, 255, stdin);

我在客户端程序的clientConnect() 方法中使用的这段代码行导致了问题。一旦我删除了recv 函数执行成功打印从客户端发送的消息的那部分。 我刚刚在网上找到了这段代码,我不知道上面这段代码发生了什么

【讨论】:

  • bzero(buffer, 256); 用 0 填充 buffer 的 256 个字节。fgets(buffer, 255, stdin);stdin(控制台)读取最多 254(255 - 1 用于空终止符)字节到 buffer然后 null 终止 buffr 将其转换为字符串。这意味着bzero 行几乎毫无价值。仅读取 254 个字节也浪费了一个字节。在线获取代码示例时要小心。他们中的许多人远不合标准。你想要的是cin.getline(buffer, sizeof(buffer));。你真正想要的是std::getlinestd::string
猜你喜欢
  • 1970-01-01
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 2012-04-02
  • 2018-01-24
  • 2021-04-14
相关资源
最近更新 更多