Windows 的 select() 用法

2021-04-23  本文已影响0人  客昂康

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);
            }
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读