【问题标题】:Assign session specific data to a socket将特定于会话的数据分配给套接字
【发布时间】:2020-06-12 21:00:29
【问题描述】:

我正在用 D 编写一个服务器应用程序,它应该能够同时管理 n 个连接。

为了实现这一点,我正在使用 std.socket.Socket.select。这工作正常。但是我无法将会话特定的数据绑定到套接字,而且我看不到任何方法可以做到这一点,因为套接字不允许保存用户特定数据的句柄。之后

Socket.select(socketSet, null, null);

我能够获取所有受影响的套接字,但我无法将此套接字分配给我的用户特定会话数据。我的错误是什么?有可能以这种方式达到我的目标吗?还是我应该根据自己的要求选择其他方式?

我的相关代码:

ushort port = 5010;
stoprequest = false;

auto listener = new TcpSocket();
assert(listener.isAlive);
listener.blocking = false;
listener.bind(new InternetAddress(port));
listener.listen(10);

enum MAX_CONNECTIONS = 100;
auto socketSet = new SocketSet(MAX_CONNECTIONS + 1);
Socket[] reads;
Session[] sessions;


while (true)
{
    socketSet.add(listener);

    foreach (session; sessions)
        socketSet.add(session.socket);

    Socket.select(socketSet, null, null);

    for (size_t i = 0; i < reads.length; i++)
    {

        if (socketSet.isSet(reads[i]))
        {
            // Now i should acces to session related data, but how?
            char[1024] buf;
            auto datLength = reads[i].receive(buf[]);

            if (datLength == Socket.ERROR)
                writeln("Connection error.");
            else if (datLength != 0)
            {
                writefln("Received %d bytes from %s: \"%s\"", datLength, reads[i].remoteAddress().toString(), buf[0..datLength]);
                continue;
            }
            else { // Error Handling. Shortened, since unimportant for the example}

            reads[i].close();

            reads = reads.remove(i);
            i--;
         }
    }

    if (socketSet.isSet(listener))
    {
        Socket sn = null;
        sn = listener.accept();

        if (reads.length < MAX_CONNECTIONS)
        {
            Session session = new Session();
            session.socket = sn;
            sessions ~= session;
        }
        else { // Error Handling for too many connection. Shortened, since unimportant for the example}}
    }

        socketSet.reset();
}

【问题讨论】:

  • 在 BSD 套接字 API 中,套接字集和选择真的很烂。你可以用select() 做的任何事情都可以用poll() 做,而poll() 在很多方面都更好。生成的数组索引立即有意义,您不必在单独的套接字数组中进行线性搜索。它不会破坏输入参数。不断地。找出什么 D 函数调用了套接字 API poll()

标签: sockets d


【解决方案1】:

使用poll() 的提示很有帮助。阅读https://daniel.haxx.se/docs/poll-vs-select.html 后,我认为这两种变体都有效,而且它们都不是真实的。为了一种有效的方式,我应该更好地处理libev。幸运的是,在这个特定项目中,效率不是我的问题。出于这个原因,我将使用select(),因为我发现访问handle 会给我一个唯一的数字,可以将它传递给自己的查找表。这允许我将会话数据分配给套接字。所以我更喜欢坚持std.socket.Socket 的封装功能,不要绕开它。

因此,我的具体问题可以这样回答:

使用 Socket.handle 来识别套接字并管理会话相关 数据

【讨论】:

    【解决方案2】:

    您可以考虑其他一些替代方案:

    1) 使用 Socket 的子类。您可以创建自己的类,从它继承并添加更多内容。

    2) poll 函数位于 import core.sys.posix.poll; 中,您也可以将 socket.handle 传递给它。但请注意,如果不进行修改,它将无法在 Windows 上运行。

    或者确实是 3) 做你自己的查找表,这也可以。

    请注意,std.socket.Socket 是 bsd 套接字 api 的一个非常薄的包装器,只是在内部它确实可以方便地处理 Windows 和 posix 之间的细微差别。仍然很容易调整代码以使用其他 api(或 C 语言的教程到 D),因为它们基本上都是一样的 - 如果你 import core.sys 东西,它们实际上是相同的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 2012-02-13
      相关资源
      最近更新 更多