1

送信と受信の両方の部分を持つこのソケットプログラムがありますが、選択を使用すると、常に「時間エラー」が返されます。ここにコードがあります

void server::run(){
int RetVal;
    struct timeval *tp=new timeval;
    tp->tv_sec=300;
    tp->tv_usec=500000;
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(sock,&readfds);
    FD_SET(sock1,&readfds);
    cout<<"run() is working fine";
    if((RetVal=select(1,&readfds,NULL,NULL,tp))==SOCKET_ERROR)  //check for incoming packets.
                {
                    cout<< "Timer error!";
                    Sleep(50);
    }
    else if(RetVal>0)   //There are incoming packets.
            {
           if(FD_ISSET(sock1, &readfds))    //incoming packet from peer host 1
         {
           send();
          }
            else if(FD_ISSET(sock, &readfds))   //incoming packet from peer host 1
           {
              send1();
          }
         else{
            cout<<"no port is open to communicate";
         }
}
}

server::server(){
WSADATA wsadata;
try{
    if (WSAStartup(0x0202,&wsadata)!=0)
        throw"Starting WSAStartup() error\n";

    //Display name of local host
    if(gethostname(servername,HOSTNAME_LENGTH)!=0) //get the hostname
        throw"Get the host name error,exit";
}
catch(char *str){
    cerr<<str<<":"<<WSAGetLastError()<<endl;
}

    printf("Server: %s waiting to be contacted for time/size request...\n",servername);
}

server::~server(){
    WSACleanup();
}

void server::send(){

try{
        if ((sock= socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
        {
            cout<< "SERVER: socket unable to initialize\n";
        }
        servers.sin_family = AF_INET;
        servers.sin_port = htons(port);
        servers.sin_addr.s_addr = INADDR_ANY;

        if (bind(sock, (sockaddr*)&servers, sizeof(servers)) == SOCKET_ERROR)
        {
            cout<<"SERVER: Cant Bind the Socket";
            closesocket(sock);
        }

       if (listen(sock, MAXPENDING) == SOCKET_ERROR)
        //if((value=listen(sock, MAXPENDING))==SOCKET_ERROR)
       {
            cout<<"SERVER: listening socket not open";
            closesocket(sock);
       }


       if ((clientSock= accept(sock, 0, 0)) == SOCKET_ERROR)
       {
           throw"SERVER: connection not accepted";
       }


       if ((nBytes= send(clientSock, "Hello", 20, 0)) == SOCKET_ERROR)
       {
           throw"SERVER: data sending failed ";
       }
    }
    catch(char *str){
    cerr<<str<<":"<<WSAGetLastError()<<endl;
    }

       closesocket(clientSock);
       closesocket(sock);
       }

void server::send1(){
try{
        if ((sock1= socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
        {
            throw "SERVER: socket unable to initialize\n";
        }
        servers.sin_family = AF_INET;
        servers.sin_port = htons(port);
        servers.sin_addr.s_addr = INADDR_ANY;

        if (bind(sock1, (sockaddr*)&servers, sizeof(servers)) == SOCKET_ERROR)
        {
            throw"SERVER: Cant Bind the Socket";
            closesocket(sock1);
        }

       if (listen(sock1, MAXPENDING) == SOCKET_ERROR)
       {
            throw "SERVER: listening socket not open";
            closesocket(sock1);
       }

       cout << "SERVER: Ready to run now...";

       if ((clientSock= accept(sock1, 0, 0)) == SOCKET_ERROR)
       {
           throw"SERVER: connection not accepted";
       }


       if ((nBytes= send(clientSock, "Hello", 20, 0)) == SOCKET_ERROR)
       {
           throw"SERVER: data sending failed ";
       }

    }
    catch(char *str){
    cerr<<str<<":"<<WSAGetLastError()<<endl;
    }

       closesocket(clientSock);
       closesocket(sock1);


}

私は非常に多くのことを試しましたが、select() は常に同じものを返します。send と recv() を直接呼び出すと、私のプログラムは run() と select() なしで正常に動作します。しかし、select()は機能していないと思います。

4

1 に答える 1

5

このselect関数は、エラー時およびタイムアウト時にSOCKET_ERROR(または実際には-1) を返します。(タイムアウトではなく) エラーが発生した場合は、 を使用して実際のエラーを取得し、このリストなどで検索する必要があります。0WSAGetLastError

また、移植可能にするために、最初の引数を最大のソケット番号 + 1 に設定する必要があります。


ただし、より大きな問題があります。呼び出したまで実際のソケットを作成しないようですselect。これは、select呼び出しで使用されるソケットが無効になることを意味し、それがエラーが発生する理由です。

通常、最初にソケットを作成し、それらをローカル アドレスにバインドして、リッスン ソケットとしてマークします。次に、ソケットで行いますselect。読み取り可能な場合、受け入れ可能な着信接続があります。

設計を再考する必要があると思います。


また、接続を受け入れた後に何が起こるかについても考慮する必要があります。現時点では、接続を受け入れ、テキストを送信してから、もう一度閉じます。しかし、受け入れられたソケットで通信を継続し、複数の接続が必要な場合は、さらに多くの作業を行う必要があります。

また、同じローカル アドレスにバインドされた 2 つのソケットを作成しようとしましたが、うまくいきません。パッシブ リスニング ソケットは、実際には 1 つだけでなく、任意の数の着信接続を受け入れることができることに注意してください。

どのソケットでデータを受信できるかを確認するには、たとえばselect、受け入れられたすべての接続とリスニング ソケットを含む読み取りセットを使用します。

于 2013-03-18T08:24:50.023 に答える