select:windows pipe的模拟

在进行socket编程时,经常会采用select或epoll来接受并发请求。在有些系统里面(例如嵌入式设备),是不支持epoll的,这时只能用select。

Select定义如下:
int select(int n, fd_set *rd_fds, fd_set *wr_fds, fd_set *ex_fds, struct timeval *timeout);

在进行select的时候,如果等待的句柄没有发生变化和没有超时,select是会一直等待在那里的。但在某些情况下,你需要唤醒select,你会怎么办呢?在linux上,你可以将管道的句柄传给select,然后在要唤醒select的时候向管道里面写东西就可以了(palm pre手机里面就用了这种技巧,我是通过反汇编知道的)。但在windows平台下,你就不能将管道传给select了,这时你就需要用socket来模拟管道了。在windows pipe的模拟(http://blog.chinaunix.net/uid-736168-id-375914.html)里面,作者提供了一种在windows上模拟管道的方法,但缺点也很明显,详细见原文,代码如下:

int pipe(int fildes[2])
{
    int tcp1, tcp2;
    sockaddr_in name;
    memset(&name, 0, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    int namelen = sizeof(name);
    tcp1 = tcp2 = -1;
    int tcp = socket(AF_INET, SOCK_STREAM, 0);
    if (tcp == -1){
        goto clean;
    }
    if (bind(tcp, (sockaddr*)&name, namelen) == -1){
        goto clean;
    }
    if (listen(tcp, 5) == -1){
        goto clean;
    }
    if (getsockname(tcp, (sockaddr*)&name, &namelen) == -1){
        goto clean;
    }
    tcp1 = socket(AF_INET, SOCK_STREAM, 0);
    if (tcp1 == -1){
        goto clean;
    }
    if (-1 == connect(tcp1, (sockaddr*)&name, namelen)){
        goto clean;
    }
    tcp2 = accept(tcp, (sockaddr*)&name, &namelen);
    if (tcp2 == -1){
        goto clean;
    }
    if (closesocket(tcp) == -1){
        goto clean;
    }
    fildes[0] = tcp1;
    fildes[1] = tcp2;
    return 0;
clean:
    if (tcp != -1){
        closesocket(tcp);
    }
    if (tcp2 != -1){
        closesocket(tcp2);
    }
    if (tcp1 != -1){
        closesocket(tcp1);
    }
    return -1;
}

你可能感兴趣的:(select:windows pipe的模拟)