我在我的服务器上使用select()以便它可以同时处理多个客户端,它可以使用带有recv()调用的select()一次性接收来自所有客户端的信息,但是当我想要使用带有send()的select()将信息发送到多个客户端,它不会一次发送到多个客户端。一旦工作客户端退出下一个客户端被处理,它将发送给一个客户端,其余客户端被阻止。我的select()逻辑错了吗?
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
fd_set write_fds; // temp file descriptor list for select()
int fdmax; // maximum file descriptor number
int newfd; // newly accept()ed socket descriptor
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
result = NULL;
recvbuflen = DEFAULT_BUFLEN;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
funcRtrnVal = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (funcRtrnVal != 0) {
printf("getaddrinfo failed with error: %d\n", funcRtrnVal);
WSACleanup();
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
// add the listener to the master set
FD_SET(ListenSocket, &master);
// keep track of the biggest file descriptor
fdmax = ListenSocket; // so far, it's this one
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
}
// Setup the TCP listening socket
funcRtrnVal = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
// error check 'bind'
if (funcRtrnVal == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
}
freeaddrinfo(result);
// listen for incoming connections
funcRtrnVal = listen(ListenSocket, SOMAXCONN);
// error check 'listen'
if (funcRtrnVal == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
}
while (true)
{
read_fds = master; // copy it
write_fds = master;
// run select statement
if (select(fdmax + 1, &read_fds, &write_fds, NULL, NULL) == -1)
{
//perror("select");
//exit(4);
}
// run through the existing connections looking for data to read/write
for (int i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
printf("read triggered\n");
if (i == ListenSocket)
{
// Accept a client socket
newfd = accept(ListenSocket, NULL, NULL);
// error check 'accept'
if (newfd == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
}
if (newfd == -1) {
//perror("accept");
}
else
{
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) { // keep track of the max
fdmax = newfd;
}
}
}
else
{
// Receive from client
funcRtrnVal = recv(i, recvbuf, recvbuflen, 0);
// if we received a byte stream
if (funcRtrnVal > 0)
{
// get the length of the byte stream
int messageLength = (int)strlen(recvbuf);
printf("%s\n", recvbuf);
}
// empty out all the buffs
memset(recvbuf, 0, sizeof(recvbuf));
//close(i); // bye!
//FD_CLR(i, &master); // remove from master set
}
}
if (FD_ISSET(i, &write_fds))
{
printf("write triggered\n");
// Send the data to the client
funcRtrnVal = send(i, sendbuf, (int)strlen(sendbuf), 0);
if (funcRtrnVal > 0)
{
printf("Server sent sendbuf: %s\n", sendbuf);
// empty out the sendbuf
memset(sendbuf, 0, sizeof(sendbuf));
}
}
}
}