【发布时间】: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 函数调用了套接字 APIpoll()。