1

私は、クライアントとサーバーがお互いの順番を待たずにチャットすることになっている、非同期/ノンブロッキング udp クライアント サーバー アプリケーションを作成したいと考えていました。これは select() でできることを知りました...

これが私のサーバーです(通信部分のみに言及):

fd_set readfds,writefds;

while(1){
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_SET(sd,&readfds);
    FD_SET(sd,&writefds);

    int rv = select(n, &readfds, NULL, NULL, NULL);
    if(rv==-1) 
    {
        printf("Error in Select!!!\n");
        exit(0);
    }
    if(rv==0) 
    {
        printf("Timeout occurred\n");
    }
    if (FD_ISSET(sd, &readfds))
    {     
        int client_length = (int)sizeof(struct sockaddr_in);
        memset(&buffer,0,sizeof(buffer));
        int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length);
        if (bytes_received < 0) {
            fprintf(stderr, "Could not receive datagram.\n");
            closesocket(sd);
            WSACleanup();
            exit(0);
        }
    }

    printf("\nClient says: %s",buffer);
    printf("\nWrite :");
    fgets(buffer,SIZE,stdin); 
    if(FD_ISSET(sd,&writefds)) {
        int client_length = (int)sizeof(struct sockaddr_in);
        if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0) {
            printf("Error sending the file! \n");
            printf("%d\n",WSAGetLastError());
            exit(1);
        }
    }
}
closesocket(sd);
WSACleanup();

return 0;

}

これは私のクライアントです:

fd_set readfds,writefds;
while(1)
{
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_SET(cs,&readfds);
    FD_SET(cs,&writefds);
    int rv=select(n,&readfds,&writefds,NULL,NULL);
            if(rv==-1)
    {
        printf("Error in Select!!!\n");
        exit(0);
    }
    if(rv==0)
    {
        printf("Timeout occurred\n");
    }
    printf("\nWrite  ");

    fgets(send_buffer,SIZE,stdin);
    if(FD_ISSET(cs,&writefds))
    {
        int server_length = sizeof(struct sockaddr_in);
        FD_CLR(cs,&writefds);

        if (sendto(cs, send_buffer, (int)strlen(send_buffer) + 1, 0, (struct sockaddr *)&server, server_length) == -1)
        {
            fprintf(stderr, "Error transmitting data.\n");
            closesocket(cs);
            WSACleanup();
            exit(0);
        }
    }

    char file_buffer[SIZE];
    //Reply reception from the server:"Ready to receive file"
    int data2=0;
    if (FD_ISSET(cs, &readfds))
    {
        FD_CLR(cs,&readfds);
        int server_length = sizeof(struct sockaddr_in);
        data2=recvfrom(cs,file_buffer,strlen(file_buffer)-1,0,(struct sockaddr *)&server,&server_length);
        //file_buffer[data2]='\0';
        if(data2<0)
        {
            printf("Server is not on:(\n");
            exit(0);
        }
    }
    //printf("%d",data2);
    printf("\nServer says:");
    for(int i=0;i<data2;i++)
    {
        putchar(file_buffer[i]);
    } 
}

return 0;
}

最初にサーバー側で次のように書きました。int rv = select(n, &readfds, &writefds, NULL, NULL);

しかし、サーバーとクライアント間の通信が適切ではないという事実に加えて、サーバーが初期化されたときに、サーバーコンソールに空の配列全体が出力されました。「&writefds」を削除すると、冗長データは削除されましたが、不適切な通信の問題は引き続き発生します...誰かが私を助けてくれたら本当にありがたいです...

4

1 に答える 1

1

あなたのコードにはいくつかの問題があります。

まず、ソケットとターミナルの両方からの入力を待ちたい場合は、両方の fd をreadfdsセットに入れる必要があります。

FD_SET(cs, &readfds);
FD_SET(stdin, &readfds);

あなたは何も書いていないので、使用すべきではありませんwritefds

次に、入力の準備ができている場合にのみ端末から読み取ろうとしていることを確認する必要があります。したがって、次のようなことを行う必要があります。

if (FD_ISSET(stdin, &readfds)) {
    // Read in from terminal...
}

あなたは現在、何が起こっても毎回読もうとしています。

file_buffer最後に、電話をかけるときにサイズを間違って測定していますrecvfromstrlenすでにデータを入れている場合にのみ機能します。を使用する必要がありますsizeof(file_buffer)

于 2013-04-20T07:19:35.580 に答える