1

我编写了以下代码以创建一个回显服务器(我写入的数据stdout从我的 PC 移动到服务器并返回到我的 PC)。问题是回显没有显示在客户端的终端上。有 2 个server.cpp进程正在运行,所以我知道我的连接已被服务器接受。完整代码在这里,您可以直接复制和运行代码。代码的相关部分是:

服务器.cpp

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;
    }
}

客户端.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));//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;
        }
    }
}
4

4 回答 4

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]

我尝试在使用-Wall -Werrorg++ 或 gcc 编译时始终使用。

于 2012-07-06T15:59:53.837 回答
1

您正在accept使用无效参数调用 server.cpp。第三个参数必须包含第二个参数指向的结构的大小:

socklen_t siz = sizeof(cli);
for(;;)
{
    if((connfd=accept(servfd, &cli, &siz))>=0)
    ...
于 2012-07-06T08:26:24.667 回答
1

你确定,你是通过在客户端输入 100 个字符stdin吗?

如果不是,您向服务器写入的字符少于 100 个,但服务器需要 100 个字符,因此服务器端会read()阻塞。

您可以通过修改客户端代码来解决这个问题,如下所示:

while (n > 0)
{  
  m = write(clifd, data, sizeof(data));
  ...

另一种方法是将客户端->服务器通信分成两部分:

1 发送要回显的数据大小

2 发送数据本身

通过这样做,您允许服务器调整要读取的字符数,然后回显。


write()只要您不检查to be返回的值,下面的这个构造就没有意义-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()");
}

此问题适用于服务器,也适用于客户端。

于 2012-07-06T16:31:04.303 回答
0

一些缩进会很好,但我也建议你重新编写它,检查不同的函数,比如“mathematician1975”。你可以在谷歌上找到很多例子。还有一个在man accept. 我建议你看看 :pollselect避免fork

于 2012-07-06T08:28:25.100 回答