select:windows pipeのシミュレーション

2078 ワード

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;
}