Windows 的 select() 与 Linux 的 select() 用法类似,但 Windows 的 select() 仅用于 socket。
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int WSAAPI select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout);
// nfds: 忽略,设置为0即可,该参数只是为了与Berkeley sockets兼容。
// readfds: 要检查可读性的socket的集合。
// writefds: 要检查可写性的socket的集合。
// exceptfds: 要检查出错的socket的集合。
// timeout: 最大等待时间,设置为NULL表示永远等待。
// 这些宏用于设置 fd_set 集合:
FD_ZERO ( *set); // 清空 fd_set 集合中所有套接字。
FD_CLR (s, *set); // 删除 fd_set 集合中的套接字 s。
FD_ISSET (s, *set); // 判断套接字 s 是否在 fd_set 集合中。
FD_SET (s, *set); // 向 fd_set 集合添加套接字 s。
用法举例:
// 对两个socket进行桥接
static void socketBridge(int socket1, int socket2){
char buffer[1024];
fd_set readfds;
struct timeval tv;
int selectError;
int recvSize;
for(;;){
// 将 socket1 和 socket2 添加到 readfds
FD_ZERO(&readfds);
FD_SET(socket1, &readfds);
FD_SET(socket2, &readfds);
// 等待 socket1 或 socket2 可读
tv.tv_sec = 60;
tv.tv_usec = 0;
selectError = select(0, &readfds, NULL, NULL, &tv);
if(selectError < 0) break;
if(selectError > 0){
// 如果 socket1 可读,读取并转发给 socket2。
if(FD_ISSET(socket1, &readfds)){
recvSize = recv(socket1, buffer, 1024, 0);
if(recvSize <= 0) break;
send(socket2, buffer, recvSize, 0);
}
// 如果 socket2 可读,读取并转发给 socket1。
if(FD_ISSET(socket2, &readfds)){
recvSize = recv(socket2, buffer, 1024, 0);
if(recvSize <= 0) break;
send(socket1, buffer, recvSize, 0);
}
}
}
}
网友评论