为什么不将客户端的输出打印到屏幕上?

时间:2019-04-17 19:10:40

标签: c sockets

我正在尝试通过套接字注入远程代码,但是由于某种原因,当编写命令cd或任何其他命令时,这反过来又通过客户端给了我一个答案,答案不会是输出到屏幕上。

我尝试了多种输出到屏幕的方法,但是它们都不起作用。

输出以下内容的服务器部分:

void *ReadAndWriteSocket(void *entrypoint) {

        char message[256];
        char buffer[256];

        while (1) {

        if((sockStructure.n = recv(sockStructure.newsockfd, buffer, strlen(buffer), 0)) > 0) { 


        for(int i = 0; i < strlen(buffer) - 1; i++) {

        printf("%s", buffer[i]);

        }

        }


        }
        scanf("%s", &message);
        send(sockStructure.newsockfd, message, strlen(message), 0);

}

客户代码:

require 'socket'
require 'open3'

def createClient(hostname, port)

  s = TCPSocket.new hostname, port

    while line = s.gets
      if line == "exit"
        s.close
      elsif line[0..1] == "cd"
        output = Dir.chdir(Dir.pwd + "/" + line[2..line.size].delete(" \t\n\r\0"))
        s.puts(Dir.pwd)
      end
      stdin, stdout, stderr, wait_thr = Open3.popen3(line)
      s.puts("#{stdout.read}")
    end
end

createClient("127.0.0.1", 8082);

1 个答案:

答案 0 :(得分:1)

即使您收到的数据量很小,也将阻塞scanf,而不是尝试接收更多数据。您可能需要同时支持双向移动数据(等待在scanf中输入数据和recv中的数据),或者在更改方向时需要更加聪明。

请考虑以下情形:

  1. 您致电ReadAndWriteSocket
  2. 您对recv的调用仅获得“ H”,即消息的第一个字节。
  3. 您将“ H”传递给printf,但由于标准输出是行缓冲的,因此没有输出任何内容。
  4. 您打电话给scanf并一直等待,但是什么也没发生,因为用户在看到收到的消息之前无意输入任何内容。
  5. 您的代码将永远不会再调用recv,这太糟糕了,因为接收到的其余消息正在接收缓冲区中等待,但是您陷于scanf中。

当您具有在两个方向上移动数据的代码时,必须绝对确保当要等待的数据向另一个方向发送时,您绝不会阻止等待一个方向的接收数据。您的代码没有什么可以防止这种情况。

更新:新代码存在问题:

void *ReadAndWriteSocket(void *entrypoint) {

    char message[256];
    char buffer[256];

    while (1) {

    if((sockStructure.n = recv(sockStructure.newsockfd, buffer, strlen(buffer), 0)) > 0) {

这是怎么回事?您只能将字符串传递给strlen。但是buffer此处不包含字符串(在第一次通过时未初始化,而在后续通过时包含无关的长度)。因此,您要将长度的荒谬值传递给recv

    for(int i = 0; i < strlen(buffer) - 1; i++) {

    printf("%s", buffer[i]);

这里有两个问题:首先,buffer[i]不是字符串,而%s格式说明符是字符串。其次,标准输出是行缓冲的,因此除非缓冲区碰巧包含一行,否则它不会显示。

    }

    }


    }
    scanf("%s", &message);

您为什么要在这里等待用户输入?如果您只收到一小部分消息,甚至没有收到整条消息,因此还没有输出任何内容怎么办?您怎么知道下一步需要做的是接收用户的输入,而不接收其余的消息?

    send(sockStructure.newsockfd, message, strlen(message), 0);
}

如果您有一些协议指定何时发送消息,谁接收消息以及何时构成消息以及何时等待用户输入,则必须编写实现该协议的代码。否则,当套接字的接收缓冲区中有数据时,您将陷入scanf中等待输入。