1

在此处输入图像描述

我编写了以下代码以创建一个回显服务器(我写入标准输出的数据从我的 PC 移动到服务器并返回到我的 PC)。问题是,尽管 echo 显示在客户端的终端上,但它的显示次数与其长度相同。

服务器.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;
}
}

客户端.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

输出

返回值 成功时,返回一个非负值。出错时,函数返回 EOF。

也许使用 write 来获取写入的字节数

于 2012-07-10T19:12:57.897 回答
0

strlen() 函数给出输入中的字符数,不包括终止 C 样式字符串的零字节。您只向服务器写入 n 个字节(没有空终止符)。然后,您读取从服务器回显的 n 个字符,并且从不设置 recvd 缓冲区的其余部分。所以它会打印内存中的任何垃圾,直到找到零为止。

于 2012-07-10T19:28:50.637 回答
0

fputs打印一个 C 字符串,而不是单个字符,因此您在 while 循环中每个字符打印整个字符串一次。此外,它依赖于以 null 结尾的字符串,而您的字符串不是。你知道长度,所以你可能会强制你自己的空终止,或者更好地创建一个std::string带有开始和长度的。

于 2012-07-10T19:18:48.653 回答
0

这段代码实际上试图打印与数组中字节数一样多的数据。它将返回写入的字节数,即 4。我认为您不需要将 puts() 和 fflush 放在一个循环中。你可以打电话给他们一次。如果您仍然想要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 回答