基于tcp传输的ftp client在控制端口发送控制指令给服务器,然后在控制端口等待服务端响应。
问题在于:《TCP/IP协议详解 v1》中介绍服务端的FTP响应指令是以回车换行符结束。只此这样的话,如果响应指令
不只一行(如FEAT指令),且每行都是不定长,客户端根本不知道这些字节流到底多大。这样导致如下的代码
每次做read都会在最后一次超时退出:
for(;;) { memset(m_cmd_recv,0,sizeof(m_cmd_recv)); FD_SET(m_control_fd,&rset); if ( (nready = select(m_control_fd + 1,&rset,NULL,NULL,&tv)) < 0) { if(errno == EINTR)//中断 continue; else { sprintf(m_errorMsg,"ControlConnRead failed:%s",strerror(errno)); return -1; } } else if (nready == 0) { sprintf(m_errorMsg,,"%s","ControlConnRead time out"); return -1; } if(FD_ISSET(m_control_fd,&rset)) { read(m_control_fd,m_cmd_recv,sizeof(m_cmd_recv)); answer += m_cmd_recv; if(string::npos != line.rfind('\n',0))//一定要找到换行符,否则认为失败读取 { break; //获得整行,需返回 } else { continue;//继续获得完整行 } } }
事实是这样吗?
基于TCP套接口的编程,客户端和服务端双方一般都要进行应用层约定来控制字节流的读取。不外乎两种:
1.请求和响应都有定长的包头和包体。这样就可以反复调用readn和writen发送指定大小的包。也就是说发送指定大小的数据,接受同样大小的数据。比如SGIP协议
2.双方以指定结束符来标记字节流的结束。我们可以多次调用read,直到碰到指定的结束标记符为止。
FTP协议明显不属于第一种约定。第二种呢,《TCP/IP 详解 v1》没明说,Ftp的RFC文档看的不知所云。那么就拿ncftp的client试试。
修改ncftp client的源码:SRead.c中增加如下的打印语句:
............... nread = read(sfd, (char *) buf, nleft); if (nread <= 0) { if (nread == 0) { /* printEOF!!!!! */ printf("EOF!!!\n\n"); if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0)) nread = (read_return_t) size - (read_return_t) nleft; goto done; } else if (errno != EINTR) { nread = (read_return_t) size - (read_return_t) nleft; if (nread == 0) nread = (read_return_t) -1; goto done; } else { errno = 0; nread = 0; /* Try again. */ /* Ignore these two lines */ LIBSIO_USE_VAR(gSioVersion); LIBSIO_USE_VAR(gCopyright); } }
编程生成可执行程序后,做如下实验:
实验1:192.168.1.102(centos系统)主机的ncftpclient连接本机的ftp服务器,执行:
./ncftpls -u baijd -p tomcatftp://192.168.1.102
打印如下:
EOF!!!
ftp.sh
ncftp-3.2.5-src.tar.bz2
实验2:用92.168.1.102(centos系统)主机的ncftpclient连接windows下的filezalla服务端,执行:
./ncftpls -u baijd -p tomcatftp://192.168.1.101
EOF!!!
$RECYCLE.BIN
64bak
debian
music
music2
System Volume Information
VGDownloads
Virtual Machines
Warcraft III
实验证明,ftp服务端真的发送EOF作为控制响应指定的结束符!!!
另记:ncftp要想GDB调试,需要执行:configure --enable-debug.其他用configure->make->make install安装的开源软件大体如此。