telnet消息结束

时间:2014-11-30 07:43:43

标签: c sockets ftp telnet

我尝试使用自己的telnet客户端与ftp服务器(特别是它的ftp.de.debian.org)进行交互。它正常工作,但在匿名登录后,ftp服务器发送欢迎消息 - 它可以在不同的包中发送数据(我是对吗?),当它发生时 - 我无法从套接字中读取它作为整个消息。当我使用GNU telnet客户端时 - 欢迎消息一次打印出来。

我尝试使用select syscall,非阻塞套接字,但结果是相同的 - 接收数据块,套接字就绪,打印出数据。 当前实施"接收响应"功能:

void recv_response(int fd, char *resp_buff, int buff_size) {

    memset(resp_buff, 0, 1024);

    fd_set rfds;
    struct timeval time;
    int ret_val;

    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);

    time.tv_sec = 1;
    time.tv_usec = 0;

    if ((ret_val = recv(fd, resp_buff, 1024, 0)) < 0 && errno != EAGAIN) {
        exit_on_error();
    } else {
        select(fd+1, &rfds, NULL, NULL, &time);
        ret_val = recv(fd, resp_buff, 1024, 0);
        printf("Bytes received: %d\n", ret_val);
        printf("%s\n", resp_buff);
    }

}

在从插座读取之前,我只使用睡眠1秒获得了正确的结果。

使用GNU telnet客户端的strace示例显示recvfrom得到了碎片消息,第一部分是142,另一部分是157。

recvfrom(3, "230- Welcome to ftp.de.debian.or"..., 8192, 0, NULL, NULL) = 142
select(4, [0 3], [1], [3], {0, 0})      = 1 (out [1], left {0, 0})
write(1, "230- Welcome to ftp.de.debian.or"..., 139230- Welcome to ftp.de.debian.org,
          hosted at Faculty of Computer Science,
                   Technische Universitaet Dresden, Germany.
) = 139
select(4, [0 3], [], [3], NULL)         = 1 (in [3])
recvfrom(3, " \r\n  If have any unusual problem"..., 8192, 0, NULL, NULL) = 157
select(4, [0 3], [1], [3], {0, 0})      = 1 (out [1], left {0, 0})
write(1, " \n  If have any unusual problems"..., 152 
  If have any unusual problems,
  please report them via e-mail to:      ftpadm@inf.tu-dresden.de

230 Anonymous access granted, restrictions apply
) = 152

那么,telnet客户端如何确定有另一部分,第一部分不应该打印到第二部分?

3 个答案:

答案 0 :(得分:0)

// you need to know how to determine if whole message has been received.

// in general, for the first char of input, use a longish wait time
// for following characters use a very short wait time.
// do this in a sequence like:

// set number of char read to 0
// set timeout to message start wait time
// while(1)
//     selectReturn = select() using timeout
//     if 0 == selectReturn (timeout event occurred, no message available or all chars read)
//     then exit loop

//     if(0 >  selectReturn (error occurred, exit loop to handle error
//     then exit loop

//     if 0 < selectReturn then
//     then, 
//        read a char and toss
//        incr number of char read, (for later comparison for validity)
//        set timeout to inter char wait time
//     end if
// end while

//  

答案 1 :(得分:0)

如果要与ftp服务器通信,则必须至少在级别实施ftp传输协议才能将输入流拆分为消息。您可以在此处找到ftp协议的规范:https://www.ietf.org/rfc/rfc959.txt。关于ftp消息格式,它说:

  

回复定义为包含3位数代码,后跟Space         ,后跟一行文字(其中一些最大行长度         已被指定),并由Telnet终止线终止         码。然而,在某些情况下,文本会长于         单行。在这些情况下,必须将完整的文本放在括号内         因此,用户进程知道何时可以停止阅读回复(即         停止处理控制连接上的输入)并继续执行其他操作         的东西。这需要第一行的特殊格式         表示不止一条线路即将到来,另一条线路正在接通         最后一行将其指定为最后一行。其中至少有一个必须         包含适当的回复代码以指示状态         交易。为了满足所有派系,两者都决定了         第一行和最后一行代码应该相同。

     

因此,多行回复的格式是第一行            将以确切的所需回复代码开头,紧随其后            立即由连字符,&#34; - &#34; (也称为Minus),其次是            文本。最后一行将以相同的代码开头,然后是            立即由Space,可选的一些文本和Telnet            行尾代码。

        For example:
                            123-First line
                            Second line
                              234 A line beginning with numbers
                            123 The last line

请注意,执行的recv的数量与服务器发送的消息数量之间没有对应关系。 TCP / IP连接只是一个字节流,可以分解为块或由路上的任何路由器以及您自己的系统连接在一起。

答案 2 :(得分:0)

实际上,telnet确实做你所描述的事情。您可以看到比较输入和输出。它有142个八位字节并打印139个字节(网络式CRLF行结束转换为单个LF),但没有第一个响应行的终止符。然后,第二个块从第一个响应行的行终止符开始。因此,telnet客户端按原样中继其输入,没有任何灌浆。

这里有两件事特别重要:

  1. Telnet客户端不会阻止来自任何一方的输入。它可以提供切换本地和远程学科的一些复杂逻辑(行缓冲或无缓冲,具有本地回声,没有一个等),但所有这些逻辑仅在特定情况下激活(telnet到端口23,来自远程服务器的控制序列) ,明确的本地选项),并且&#34;睡觉&#34;在你的例子中。默认情况下,本地终止规则配置为行缓冲,因此,您的请求将不会从终端发送到telnet,直到按下Enter键。 OTOH,立即打印远程数据。如果遥控器没有等待您的请求,这可能会导致屏幕上出现混乱。
  2. FTP有自己的结构,声明响应是使用特殊语法发送的。特别是,任何响应行都以数字代码开头,如果该行不是最后一个响应行,则此代码后跟连字符而不是空格。因此,FTP客户端读取行(每行应以CRLF终止以被视为正确接收),如果检测到该行具有连续符号(&#39; - &#39;在初始数字后),则等待下一行
  3. 要获得进一步的进展,请说明您到底想要达到的目标。这是telnet客户端,FTP客户端还是其他什么?