对 select() 的困惑
Confusion about select()
忙了2天了还是没看懂。 select()
在这段代码中做了什么?
我知道如果有一个可以接受的传入连接,copy.fd_array[]
将包含 ListenSocket
但是当 while 循环重复时它仍然存在。那么我们如何知道客户端是否断开连接呢? fd_set copy
在 select()
调用之后包含什么?
fd_set master;
FD_ZERO(&master);
FD_SET(ListenSocket, &master);
while (1)
{
fd_set copy = master;
select(FD_SETSIZE, ©, NULL, NULL, NULL);
for (int i = 0; i < FD_SETSIZE; i++)
{
// If new connection
if (FD_ISSET(ListenSocket, ©))
{
printf("[+] New connection\n");
// Accept connection
SOCKET AcceptedClient = accept(ListenSocket, NULL, NULL);
FD_SET(AcceptedClient, &master);
// Send welcome message to client
char buff[128] = "Hello Client!";
send(AcceptedClient, buff, sizeof(buff), 0);
}
}
}
I'm busy with this for 2 days now and still don't understand it.
难怪看不懂代码:例子里的代码都是废话
检查 ListenSocket
应该在 for
循环之外完成。并且 FD_ISSET
还必须检查使用 accept
.
接受的连接
while
循环中的正确代码如下所示:
fd_set copy = master;
select(FD_SETSIZE, ©, NULL, NULL, NULL);
// If new connection
if (FD_ISSET(ListenSocket, ©))
{
...
}
for (int i = 0; i < FD_SETSIZE; i++)
{
// If an existing connection has data
// or the connection has been closed
if ((i != ListenSocket) && FD_ISSET(i, ©))
{
nBytes = recv(i, buffer, maxBytes, 0);
// Connection dropped
if(nBytes < 1)
{
close(i); // other OSs (Linux, MacOS ...)
// closesocket(i); // Windows
FD_CLR(i, &master);
}
// Data received
else
{
...
}
}
}
I know that if there is an incoming connection that can be accepted, the copy.fd_array[]
will contain ListenSocket
but when the while
loop repeats it's still there.
What does fd_set copy contain after the select() call?
首先:在调用select()
之前,copy.fd_array[]
必须包含所有你感兴趣的套接字句柄。这意味着它必须包含ListenSocket
和所有 句柄由 accept()
.
返回
master.fd_array[]
包含所有这些句柄,因此 fd_set copy = master;
将确保 copy.fd_array[]
也包含所有这些句柄。
select()
(NULL
作为最后一个参数)将等待至少一个套接字变为“可用”。这意味着它将等到至少以下条件之一为真:
- 使用
accept()
接受的连接已被对方关闭
- 使用
accept()
接受的连接有可以接收的数据
- 有一个可以接受的新连接
accept(ListenSocket...)
只要满足一个条件,select()
就会从 copy.fd_array[]
中删除 所有其他句柄:
如果没有传入连接,ListenSocket
将从copy.fd_array[]
中删除
- 如果连接既没有关闭也没有新数据可用,则
accept()
返回的句柄将从该数组中删除
如果两个事件同时发生,copy.fd_array[]
将包含多个句柄。
您使用 FD_ISSET()
检查一些句柄是否仍在数组中。
So how do we know if a client is disconnected?
当您检测到 FD_ISSET(i, ©)
的值 i
已由 accept()
返回时,您必须调用 recv()
(在 Linux read()
也可以):
如果recv()
returns 0(或错误情况下为负),另一台计算机已断开连接。您必须调用 close()
(Windows 上的 closesocket()
)并从 copy.fd_array[]
中删除句柄(这意味着:您必须从 master.fd_array[]
中删除它,因为行 fd_set copy = master;
).
如果recv()
returns 为正值,则这是已接收的字节数。
忙了2天了还是没看懂。 select()
在这段代码中做了什么?
我知道如果有一个可以接受的传入连接,copy.fd_array[]
将包含 ListenSocket
但是当 while 循环重复时它仍然存在。那么我们如何知道客户端是否断开连接呢? fd_set copy
在 select()
调用之后包含什么?
fd_set master;
FD_ZERO(&master);
FD_SET(ListenSocket, &master);
while (1)
{
fd_set copy = master;
select(FD_SETSIZE, ©, NULL, NULL, NULL);
for (int i = 0; i < FD_SETSIZE; i++)
{
// If new connection
if (FD_ISSET(ListenSocket, ©))
{
printf("[+] New connection\n");
// Accept connection
SOCKET AcceptedClient = accept(ListenSocket, NULL, NULL);
FD_SET(AcceptedClient, &master);
// Send welcome message to client
char buff[128] = "Hello Client!";
send(AcceptedClient, buff, sizeof(buff), 0);
}
}
}
I'm busy with this for 2 days now and still don't understand it.
难怪看不懂代码:例子里的代码都是废话
检查 ListenSocket
应该在 for
循环之外完成。并且 FD_ISSET
还必须检查使用 accept
.
while
循环中的正确代码如下所示:
fd_set copy = master;
select(FD_SETSIZE, ©, NULL, NULL, NULL);
// If new connection
if (FD_ISSET(ListenSocket, ©))
{
...
}
for (int i = 0; i < FD_SETSIZE; i++)
{
// If an existing connection has data
// or the connection has been closed
if ((i != ListenSocket) && FD_ISSET(i, ©))
{
nBytes = recv(i, buffer, maxBytes, 0);
// Connection dropped
if(nBytes < 1)
{
close(i); // other OSs (Linux, MacOS ...)
// closesocket(i); // Windows
FD_CLR(i, &master);
}
// Data received
else
{
...
}
}
}
I know that if there is an incoming connection that can be accepted, the
copy.fd_array[]
will containListenSocket
but when thewhile
loop repeats it's still there.
What does fd_set copy contain after the select() call?
首先:在调用select()
之前,copy.fd_array[]
必须包含所有你感兴趣的套接字句柄。这意味着它必须包含ListenSocket
和所有 句柄由 accept()
.
master.fd_array[]
包含所有这些句柄,因此 fd_set copy = master;
将确保 copy.fd_array[]
也包含所有这些句柄。
select()
(NULL
作为最后一个参数)将等待至少一个套接字变为“可用”。这意味着它将等到至少以下条件之一为真:
- 使用
accept()
接受的连接已被对方关闭 - 使用
accept()
接受的连接有可以接收的数据 - 有一个可以接受的新连接
accept(ListenSocket...)
只要满足一个条件,select()
就会从 copy.fd_array[]
中删除 所有其他句柄:
-
如果没有传入连接,
ListenSocket
将从copy.fd_array[]
中删除- 如果连接既没有关闭也没有新数据可用,则
accept()
返回的句柄将从该数组中删除
如果两个事件同时发生,copy.fd_array[]
将包含多个句柄。
您使用 FD_ISSET()
检查一些句柄是否仍在数组中。
So how do we know if a client is disconnected?
当您检测到 FD_ISSET(i, ©)
的值 i
已由 accept()
返回时,您必须调用 recv()
(在 Linux read()
也可以):
如果recv()
returns 0(或错误情况下为负),另一台计算机已断开连接。您必须调用 close()
(Windows 上的 closesocket()
)并从 copy.fd_array[]
中删除句柄(这意味着:您必须从 master.fd_array[]
中删除它,因为行 fd_set copy = master;
).
如果recv()
returns 为正值,则这是已接收的字节数。