【问题标题】:Sockets: send messages to several clients套接字:向多个客户端发送消息
【发布时间】:2018-05-16 21:11:40
【问题描述】:

我正在尝试编写一个服务器,它接受来自多个客户端的消息,直到它接收到其中 N 个,处理这批数据并将回复“完成”发送给所有客户端。

如果我在收到来自客户端的数据后立即向客户端发送“完成”消息,则此代码可以正常工作。如何在批处理完成后“保存”所有客户端并稍后将消息发送给每个客户端?

while (true) {
    listen(sock, 1000);
    newsock = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
    n = read(newsock, buffer, read_len);
    if (n < 0) {
        cout << "ERROR reading from the socket" << endl;
        continue; 
    }
    memcpy(data + (msg_count * tuple_size), buffer, tuple_size);
    n = write(newsock, "done\n", 5); //sending the message to the current client
    msg_count++;
    if (msg_count >= batch_size) {
        msg_count = 0;
        doSomethingWithTheData(data);
        //I want to send the message to all the clients here
    }
    bzero(buffer, read_len);
}

【问题讨论】:

  • 你试过设置cookies吗?
  • @ArashMohammadi 不,我没有尝试过,我现在要阅读它。如果服务器和所有客户端都在同一台 PC 上,cookie 会起作用吗?
  • 如果客户端可以发送多条消息,您可能需要查看selectepoll
  • 目前每个客户端只有一条消息,客户端只能为下一批发送下一条消息。
  • 另请注意:read 不保证您会收到完整的消息。您将收到 0 到 read_len 字节。 n 是实际读取的字节数,0 表示套接字断开连接。如果n 小于消息所需的字节数,则必须循环直到获得整个消息。

标签: c++ sockets


【解决方案1】:

试试这样的。

while (true) {
    std::list<int> socks;
    listen(sock, 1000);
    newsock = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
    n = read(newsock, buffer, read_len);
    if (n < 0) {
        cout << "ERROR reading from the socket" << endl;
        continue; 
    }
    memcpy(data + (msg_count * tuple_size), buffer, tuple_size);
    socks.push_back(newsock);
    msg_count++;
    if (msg_count >= batch_size) {
        msg_count = 0;
        doSomethingWithTheData(data);

        //I want to send the message to all the clients here
        msg_count -= socks.size();
        while (!socks.empty()) {
            newsock = socks.front();
            n = write(newsock, "done\n", 5); //sending the message to the current client
            close(newsock);
            socks.pop_front();
        }
    }
    bzero(buffer, read_len);
}

仅供参考 bzero() 函数已弃用(在 POSIX.1-2001 中标记为 LEGACY):在新程序中使用 memset(3)。 POSIX.1-2008 删除了 bzero() 的规范

【讨论】:

  • 正确。 vgeclair 无论如何你都必须做这样的事情,因为目前你只是分配袜子而没有释放它们。
  • 我刚试过,但它在这一行给出了“Broken pipe”错误:n = write(sock, "done\n", 5); 你确定我应该将sock 添加到列表中而不是newsock 吗?它似乎总是具有相同的值。
  • 你似乎是对的,@vgeclair。 sock 是您正在监听的套接字,而不是连接到客户端的套接字。
  • 但如果我改为添加newsock,它就不起作用(虽然值不同)并且客户端不会收到消息。
  • 我错了,它可以工作(如果我用newsock 替换sock 并在循环之前创建列表),问题是由客户端的某些东西引起的。谢谢!
【解决方案2】:

你试过 zeroMq 吗? 例如http://zguide.zeromq.org/cpp:rrworker

【讨论】:

  • 不,我没试过。记住几个客户有什么帮助?
  • 我的想法是扩展请求-回复模式,其中 n 客户端连接到前端套接字并将其分派给批处理工作人员。工作人员完成工作后,前端套接字响应 n 个客户端
猜你喜欢
  • 2016-08-31
  • 1970-01-01
  • 2017-08-14
  • 2017-07-01
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-25
  • 2013-04-01
相关资源
最近更新 更多