1

首先让我说这是操作系统课程的家庭作业,我不是程序员,尤其不是 C 语言。我已经在这工作了一个星期了,我只是卡住了,我需要帮助。我必须创建 TCP 客户端和服务器应用程序,其中将 linux 命令键入客户端,在服务器上执行并将输出重定向回客户端。我理解这个概念,我有 90+% 的工作。“ls”、“ls -lpq”、“cat somefile”、“man somecommand”等命令都可以正常工作。我遇到麻烦的地方是命令不返回任何信息,如“mkdir newdir”(如果目录已经存在,它可以正常工作,因为我得到了响应)。这对我来说是全新的,但在我看来,我的问题在于服务器的 recv 命令阻塞,因为没有信息可以接收。我不知道如何解决这个问题,我已经在这个问题上工作了一周。我的时间不多了,我还必须实现文件上传和下载,我不知道从哪里开始,但在我解决这个问题之前我什至无法开始工作。

谢谢

    // this is where I think the problem is
    while ((rcvd_bytes = recv(sock_fd, recv_str, sizeof(recv_str), 0)) > 0 ) {
        // Zero out the inputCopy buffer
        memset(&inputCopy, 0, sizeof(inputCopy)+1);

        // Copy the recv_str into a new string so that
        // we can work with it.
        strcpy(inputCopy, recv_str);

        argcount = parsecommand(inputCopy, args);

        //Send the message back to client
        dup2(sock_fd, 1);

        if((status = forkAndExecute(args)) != 0) {
            //printf("Command %s returned %d.\n", args[0], status);
        }

            // as a test is I uncomment the following line mkdir newdir
            // returns but the following commands are messed up - as I expect.
        //printf("\n");

        memset(&recv_str, 0, sizeof(recv_str)+1);
        fflush(stdout);
    }  

    if(rcvd_bytes == 0) {
    puts("Client disconnected");
    fflush(stdout);
    }
    else if(rcvd_bytes == -1) {
    perror("recv failed");
    exit(0);
    }
4

2 回答 2

3

听起来您需要使用select

if(select(fdmax+1, &my_fdset, 0, 0, NULL) > 0) // there is data available to be read
    recv(...)

其中fdmax是最大的文件描述符(select 想要 +1)并且my_fdset是一个文件描述符集,您可以将文件描述符添加到 using FD_SET(sockfd, &my_fdset);.

这只会在有可用数据时接收。希望有帮助。

编辑 :

当我编写一个简单的客户端/服务器程序以通过 TCP 套接字发送/接收字符串时,我问了一个类似的问题。我在这里发布了我最终在该线程上使用的代码。我的不同之处在于我想要一个程序来发送和接收,但是如果你看看我的发送者或接收者函数,你可能能够调整一些东西来让你的程序做你想做的事。

于 2013-03-22T03:32:45.163 回答
1

鉴于您的问题描述,我怀疑是客户端代码而不是服务器代码 - 或者实际上是您在两者之间隐式创建的协议。

看起来您只是通过使用dup2将标准输出指向套接字将命令的输出直接发送回客户端。大概,客户端然后从套接字读取以获取命令的输出?当客户端向服务器发送命令然后没有得到回复时,客户端会做什么?像这样的命令mkdir不会发回任何东西。是否永远等待服务器发送命令输出?

一般来说,对于同步客户端/服务器协议(客户端发送命令,服务器在客户端发送另一个命令之前发送响应的协议),您必须在客户端和服务器之间就协议达成一致,以清楚地指示何时服务器完成发回数据,客户端应该发送下一个命令。您可能需要为服务器添加一些方法来告诉客户端命令已完成但未发送任何输出。

于 2013-03-22T03:38:43.593 回答