select的列子说明select内部实现原理
1:select內(nèi)部是個數(shù)組,而epoll內(nèi)部結(jié)構(gòu)是紅黑二叉樹
2:select查詢起來慢,而epoll查詢起來快
3:每次循環(huán),內(nèi)部都要發(fā)生拷貝(查看相關(guān)代碼)而epoll不需要這樣的操作,也就是初始化一次拷貝
#include
#include<winsock2.h>
#include<windows.h>
#include
#include
int main()
{
std::vectorclients;
WSAData data;
if (WSAStartup(MAKEWORD(2, 2), &data) == SOCKET_ERROR) {
std::cout << (“WSAStartUp Error”) << std::endl;
}
SOCKET socket_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in add_ress;
add_ress.sin_family = AF_INET;
add_ress.sin_port = htons(8080); //綁定端口號
add_ress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //能夠接受任意ip地址消息
bind(socket_fd, (sockaddr*)&add_ress, sizeof(add_ress));
listen(socket_fd, 5);在這里插入代碼片
fd_set read_fd;
fd_set temp_fd;
FD_ZERO(&read_fd);
FD_ZERO(&temp_fd);
FD_SET(socket_fd, &read_fd);
TIMEVAL tv;//設(shè)置超時等待時間
tv.tv_sec = 1;
tv.tv_usec = 0;
std::size_t max_fd = socket_fd;
while (1) {
temp_fd = read_fd;
//因為底層內(nèi)部實現(xiàn)會刪除temp_fd的集合,因此要加一個局部數(shù)據(jù)
int ret = select(max_fd + 1, &temp_fd, NULL, NULL, &tv); //最后一個參數(shù)表上阻塞
if (ret == -1) {
break;
}
//如果socket_fd在temp_fd集合內(nèi),說有事件來了
if (FD_ISSET(socket_fd, &temp_fd)) {
sockaddr_in add_client;
int len = sizeof(add_client);
SOCKET client_fd = accept(socket_fd, (SOCKADDR*)&add_client, &len);
clients.emplace_back(client_fd);
FD_SET(client_fd, &read_fd);
auto fd = std::find_if(clients.begin(), clients.end(), [max_fd](SOCKET fd)->bool {return fd > max_fd;});
if (fd != clients.end()) {
max_fd = *fd; //更新fd
}
}
else {
//其實從這地方也能看出,select的底層結(jié)構(gòu)是數(shù)組,
int count = clients.size();
for (int i = 0;i < count;++i) {
if (FD_ISSET(clients[i], &temp_fd)) {
char buffer[100] = { 0 };
int bytes = recv(clients[i], buffer, 100, 0);
if (bytes == -1) {
continue;
}
if (bytes == 0) {//客戶端退出了
SOCKET temp_fd = clients[i];
closesocket(temp_fd);
clients.erase(clients.begin()+i);
FD_CLR(temp_fd, &read_fd);
//read_fd.fd_array[i] = 0; //傻逼底層,竟然不刪除,垃圾
auto fd = std::find_if(clients.begin(), clients.end(), [max_fd](SOCKET fd)->bool {return fd > max_fd;});
if (fd == clients.end()) {
max_fd = socket_fd;
}
else {
max_fd = *fd; //更新fd
}
continue;
}
else {
//處理消息, 不寫了
}
}
}
}
}
}
總結(jié)
以上是生活随笔為你收集整理的select的列子说明select内部实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 切割图形_泉州泡沫景观字切割机厂家
- 下一篇: 基于SpringMVC进行REST服务开