c - 如何让服务器在第一个客户端后不等待接受?
问题描述
我有一个 tcp 服务器,我想制作它,所以在它接受第一个客户端后,它不会等待接受函数,如果没有其他人连接,它就会继续
while (1)
{
SOCKET ClientSocket = accept(Socket, (sockaddr *)&Client, &ClientSize);
if(ClientSocket == INVALID_SOCKET)
{
Error("accept failed.\n");
}
ClientSockets[ClientSocketsIndex++] = ClientSocket;
Result = connect(ClientSocket, (sockaddr*)&Client, ClientSize);
sockaddr_in From;
int FromSize = sizeof(From);
Result = recv(ClientSocket, Message, sizeof(Message), 0);
if (Result == SOCKET_ERROR)
{
Error("recv failed.\n");
}
Result2 = getpeername(ClientSocket, (sockaddr*)&From, &FromSize);
if (Result2 == SOCKET_ERROR)
{
Error("getpeername failed.\n");
}
在这里,我使用 ClientSocketaccept()
并将其添加到存储所有 ClientSocket 的数组中,然后接收缓冲区。问题是在每个循环之后它都会等待一个新的 ClientSocket。
该Error()
功能只是我为打印到控制台并在遇到错误 btw 时退出的功能。
解决方案
首先,调用connect()
return SOCKET
byaccept()
是错误的。摆脱它。
其次,如果您希望您的循环正确地为多个客户端提供服务,请使用select()
(或等效)。在告诉您新客户正在等待接受accept()
之前不要打电话。同样,在告诉您阵列中的客户端正在等待读取之前select()
不要打电话。recv()
select()
尝试更多类似的东西:
const size_t MAX_SOCKETS = ...;
SOCKET ClientSockets[MAX_SOCKETS];
size_t NumClientSockets = 0;
...
while (true)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(Socket, &readfds);
for(int i = 0; i < NumClientSockets; ++i)
{
FD_SET(ClientSockets[i], &readfds);
}
if (select(0, &readfds, NULL, NULL, NULL) > 0)
{
if (FD_ISSET(Socket, &readfds))
{
ClientSize = sizeof(Client);
SOCKET ClientSocket = accept(Socket, (sockaddr *)&Client, &ClientSize);
if (ClientSocket == INVALID_SOCKET)
{
Error("accept failed.\n");
}
else if (NumClientSockets == MAX_SOCKETS)
{
closesocket(ClientSocket);
}
else
{
ClientSockets[NumClientSockets] = ClientSocket;
++NumClientSockets;
}
}
size_t i = 0;
while (i < NumClientSockets)
{
if (!FD_ISSET(ClientSockets[i], &readfds))
{
++i;
continue;
}
Result = recv(ClientSockets[i], Message, sizeof(Message), 0);
if (Result <= 0)
{
if (Result == SOCKET_ERROR)
Error("recv failed.\n");
for(size_t j = i + 1; j < NumClientSockets; ++j)
{
ClientSockets[j - 1] = ClientSockets[j];
}
--NumClientSockets;
continue;
}
// use Message up to Result bytes as needed...
++i;
}
}
}
推荐阅读
- javascript - 减小 html2canvas 图像大小
- android - 将广播从 App A 发送到 App B 并返回
- laravel - NGINX:从位置到端口的反向代理
- python - 有没有办法从 boto3 中当前运行的 EC2 实例创建 LaunchTemplate?
- python - Python Json以特定格式提取指标值
- powerbi - Power Pivot 中上个月和当前月份之间的差异
- python-3.x - PIL 替代保存/覆盖像素?
- asp.net-mvc - 在 ASP.NET MVC 中使用 POST 操作返回文件流
- hyperledger-fabric - Hyperledger 开发:是否可以用 Fabric 中的 Raft 替代另一个共识系统?
- mysql - MySQL8.0 Workbench 添加连接时出错