我编写了以下代码以制作一个echo服务器(我写入stdout的数据从我的PC移动到服务器并返回到我的PC)。问题是尽管echo已经显示在客户端的终端上了与其长度显示的次数相同。
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;
}
}
}
有什么问题?
答案 0 :(得分:2)
的fputs
返回值 成功时,返回非负值。 出错时,函数返回EOF。
也许使用write来获取写入的字节数
答案 1 :(得分:0)
fputs
打印一个C字符串,而不是单个字符,因此您在while循环中每个字符打印整个字符串一次。此外,它依赖于字符串为空终止,而你的字符串不是。你知道长度,所以你可能强迫你自己的空终止或更好地创建一个带有开始和长度的std::string
。
答案 2 :(得分:0)
此代码实际上是尝试打印数据的次数与数组中的字节数一样多。它将返回写入的字节数,即4.我认为你不需要在循环中使用puts()和fflush。你可以打电话给他们一次。如果您仍想要while循环,可以检查返回值(m)并与数据长度(n)进行比较,如果它们相等,则从循环中断。
最后while循环可以替换为
fputs(data,stdout);
fflush(stdout);
希望这有帮助。
答案 3 :(得分:0)
如果新数据到达,您将处理缓冲区。
您可以在阅读数据的位置更改此内容:
for(;;)
{
if(fgets(data, 100,stdin )) { /* only process the data, when something arrived. */
n=strlen(data);
cout<<"You have written "<<n<<endl;
...
答案 4 :(得分:0)
strlen()函数给出输入中的字符数,不包括终止C样式字符串的零字节。您只向服务器写入n个字节(没有空终止符)。然后你读取从服务器回送的n个字符,并且永远不会设置recvd缓冲区的剩余部分。因此,它会打印内存中的任何垃圾,直到它找到零。