我编写了以下代码以便创建一个echo服务器(我写入stdout
的数据从我的PC移动到服务器并返回到我的PC)。问题是回声没有显示在客户端的终端上。有2个server.cpp
进程正在运行,所以我知道我的连接已被服务器接受。完整代码为here,以便您可以直接复制和运行代码。代码的相关部分是:
void reflect(int x)
{
int n;
int m;
char data[100];
cout<<"Entered reflect function"<<endl; //this gets displayed
n=read(x,data, 100); //***execution is not going beyond this point i.e. read is blocking***
cout<<"Client sent "<<n<<endl; //this doesn't get displayed
if(n>0)
{
while(n>0)
{
m=write(x,data,n);
n=n-m;
}
cout<<"Successfully echoed back to client"<<endl; //this doesn't get displayed
}
}
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;
}
}
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));//blocking call
int n,m;
char data[100];
char recvd[100];
for(;;)
{
fgets(data, 100,stdin );
n=strlen(data);
cout<<"You have written "<<n<<endl; //this returns the correct value
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; //this doesn't get displayed
if(n>0)
{
while(n>0)
{
m=fputs(data,stdout);
fflush(stdout);
n=n-m;
}
//cout<<data<<endl;
}
}
}
答案 0 :(得分:3)
在server.c中,替换错误的行:
if( connfd=accept(servfd, &cli, &siz) >=0 )
用这个正确的:
if( (connfd=accept(servfd, &cli, &siz)) >=0 )
<小时/> 除了:您使用的是什么编译器?当看到该行时,g ++打印出警告:
serv.cc: In function ‘int main()’:
serv.cc:45:43: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
在使用g ++或gcc编译时,我尝试始终使用-Wall -Werror
。
答案 1 :(得分:1)
您使用无效参数调用server.cpp中的accept
。第三个参数必须包含第二个参数指向的结构的大小:
socklen_t siz = sizeof(cli);
for(;;)
{
if((connfd=accept(servfd, &cli, &siz))>=0)
...
答案 2 :(得分:1)
您确定,您是通过stdin
在客户端输入100个字符吗?
如果没有,您向服务器写入的字符少于100个,但服务器需要100个字符,因此服务器端read()
会阻塞。
您可以通过修改客户端代码来解决此问题:
while (n > 0)
{
m = write(clifd, data, sizeof(data));
...
另一种方法是将客户端 - >服务器通信分成两部分:
1发送要回显的数据大小
2自行发送数据
通过这样做,您可以让服务器调整要读取的字符数,然后回显。
只要不将write()
返回的值检查为-1
,下面的结构就没有意义。
对write()
的调用将阻塞,直到写入n
个字节,或者在出错时返回-1
。后者会制造你的逻辑。
while (n > 0)
{
m=write(fd, data, n);
n = n - m;
}
你可能想尝试这样的事情:
while (n > 0)
{
m = write(fd, data, n);
if (0 < m)
n = n - m;
else if (errno)
perror("write()");
}
此问题适用于服务器以及客户端。
答案 3 :(得分:0)
一些缩进会很好,但我也建议你重新编写它,检查不同的函数,如“mathematician1975”。
你可以在谷歌上找到很多例子。还有man accept
中的一个。
我建议您查看:poll
或select
以避免fork