1

ここに画像の説明を入力してください

エコーサーバーを作成するために、次のコードを記述しました(stdoutに書き込んだデータは、PCからサーバーに移動してPCに戻ります)。問題は、エコーがクライアントの端末に表示されているにもかかわらず、その長さと同じ回数表示されていることです。

server.cpp

void reflect(int x)
{
int n;
int m;
char data[100];
cout<<"Entered reflect function"<<endl; 

for(;;)
{
n=read(x,data, 100); 
cout<<"Client sent "<<n<<endl; 

if(n>0)
{
    while(n>0)
    {
        m=write(x,data,n);
        n=n-m;
    }
cout<<"Successfully echoed back to client"<<endl;  
}
}//end of for loop
}

int main()
{
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));

int servfd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int x;
x=bind(servfd, (sockaddr*)(&serv), sizeof(serv));

cout<<"Bind returned"<<x<<endl; //this displays x as 0

listen(servfd, 5);
sockaddr cli;
int connfd;
pid_t id=-1;
socklen_t siz=sizeof(cli);
for(;;)
{
    if((connfd=accept(servfd, &cli, &siz))>=0)
         id=fork();

    if(id==0)
         reflect(connfd);

    else 
         continue;
}
}

client.cpp

int main()
{
int clifd;
clifd=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));

connect(clifd, (sockaddr*)(&serv), sizeof(serv));
int n,m;
char data[100];
char recvd[100];
for(;;)
{
    fgets(data, 100,stdin );
    n=strlen(data);
    cout<<"You have written "<<n<<endl;

    if(n>0)
    {
        while(n>0)
        {  
             m=write(clifd,data,n);
             n=n-m;
        }
    }

    n=read(clifd, recvd, 100);
    cout<<"Server echoed back "<<n<<endl; 

    if(n>0)
    {
        while(n>0)
        {
            m=fputs(data,stdout);  //gets displayed many times
            cout<<"m is"<<m<<endl; //gets displayed many times
            fflush(stdout);
            n=n-m;
        }
        //cout<<data<<endl;
    }
}
}

何が問題ですか?

4

5 に答える 5

2

fputs

戻り値成功すると、負でない値が返されます。エラーの場合、関数はEOFを返します。

代わりにwriteを使用して、書き込まれたバイト数を取得します。

于 2012-07-10T19:12:57.897 に答える
0

fputs1文字ではなくC文字列を出力するため、whileループでは文字ごとに1回文字列全体を印刷します。さらに、それはあなたのものではないnullで終了する文字列に依存しています。あなたは長さを知っているので、おそらくあなた自身のヌル終了を強制するか、それでもstd::string開始と長さでを作成することができます。

于 2012-07-10T19:18:48.653 に答える
0

このコードは、実際には配列内のバイト数と同じ回数だけデータを出力しようとしています。書き込まれたバイト数(4)が返されます。puts()をループでフラッシュする必要はないと思います。あなたはそれらを一度呼び出すことができます。それでもwhileループが必要な場合は、戻り値(m)を確認し、データの長さ(n)と比較して、それらが等しい場合はループから抜けることができます。

最後のwhileループは次のように置き換えることができます

fputs(data,stdout);
fflush(stdout);

お役に立てれば。

于 2012-07-10T19:20:37.030 に答える
0

新しいデータが到着したかどうかにかかわらず、バッファを処理します。

データを読み取る場所でこれを変更できます。

for(;;)
{
    if(fgets(data, 100,stdin )) { /* only process the data, when something arrived. */
        n=strlen(data);
        cout<<"You have written "<<n<<endl;
        ...
于 2012-07-10T19:23:08.723 に答える
0

strlen()関数は、Cスタイルの文字列を終了するゼロバイトを除いた入力の文字数を示します。サーバーに書き込むのはnバイトのみです(ヌルターミネータなし)。次に、サーバーからエコーバックされたn文字を読み取り、recvdバッファーの残りを設定することはありません。したがって、ゼロが見つかるまで、メモリ内にあるすべてのジャンクを出力します。

于 2012-07-10T19:28:50.637 に答える