Socket网络编程--FTP客户端(2)(Windows)
2015-05-28 18:55
393 查看
上一篇FTP客户端讲到如果制作一个简单的FTP客户端,功能实现了,但是后面我们发现了问题,就是FTP是使用明文进行操作的。对于普通情况来说就无所谓了。但有时候要安全的一点的话,就应该使用FTP的安全版本。有SFTP和FTPs,两者都是FTP的安全版本,但是两者的实现原理差别还是很大的,具体自己搜索了解。
0.环境安装
环境使用我的这一篇文章安装好libssh2库。
http://www.cnblogs.com/wunaozai/p/4528394.html
使用一个带有SFTP功能的FTP服务器。注意有些FTP服务器是不带SFTP功能的。这里我使用这个FreeSSHd作为SFTP服务器。
http://www.freesshd.com/?ctt=download
关于freesshd配置说两句,Server status标签 点击确定SSH server is running。SSH标签,确定配置完成。Authentication标签下Password authentication为Allowed,Public key authentication为Disabled,这样做的原因是我接下来要做的程序只支持密码登录,减少不必要的干扰,如果有需要,可以自己设定。Tunneling标签,所有选项选中,如果没有选中,本地如果网络复杂的话,可能会有问题。SFTP标签,选择一个作为FTP的根目录。Users标签,增加一个用户。基本设置就这些了。
View Code
至于用到的libssh2_config.h这个文件,没有的话可以在代码中注释掉.
下面这个是freesshd产生的日志中一部分
有了上面这两个主要的功能,SFTP的客户端就基本功能实现了,至于mkdir和dir功能就参考里面的示例程序,基本都可以看懂。
3.使用putty连接freesshd
了解过SFTP原理之后,就知道,SFTP其实跟FTP没有多大的关系,其实就是一个使用SSH协议,然后进行会话,会话过程保存为文件,嗯,大概就是这个样子了。所以我们可以使用普通的ssh软件进行登录,拿到该SFTP服务器站点的SHELL。然后可以各种操作,看起来很危险的样子,所以不管用什么SFTP服务器在配置用户的时候要注意的。 putty工具里面还有个PSFTP.exe这个工具可以连接到SFTP服务器,没事的也可以玩玩看。
本文地址: /article/6193159.html
0.环境安装
环境使用我的这一篇文章安装好libssh2库。
http://www.cnblogs.com/wunaozai/p/4528394.html
使用一个带有SFTP功能的FTP服务器。注意有些FTP服务器是不带SFTP功能的。这里我使用这个FreeSSHd作为SFTP服务器。
http://www.freesshd.com/?ctt=download
关于freesshd配置说两句,Server status标签 点击确定SSH server is running。SSH标签,确定配置完成。Authentication标签下Password authentication为Allowed,Public key authentication为Disabled,这样做的原因是我接下来要做的程序只支持密码登录,减少不必要的干扰,如果有需要,可以自己设定。Tunneling标签,所有选项选中,如果没有选中,本地如果网络复杂的话,可能会有问题。SFTP标签,选择一个作为FTP的根目录。Users标签,增加一个用户。基本设置就这些了。
#include "libssh2_config.h" #include <libssh2.h> #include <libssh2_sftp.h> #include <winsock2.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <ctype.h> #define PORT 22 #define HOST "127.0.0.1" #define USER "user" #define PWD "user" #define FILENAME "wunaozai.txt" #define LOCLFILE "wunaozai.txt" long tvdiff(struct timeval newer, struct timeval older); int waitsocket(int socket_fd, LIBSSH2_SESSION *session); int main(int argc, char *argv[]) { int sock, i; struct sockaddr_in sin; const char *fingerprint; LIBSSH2_SESSION *session; LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP_HANDLE *sftp_handle; struct timeval start; struct timeval end; int total = 0; long time_ms; int spin = 0; int ret=0; int rc=1; FILE * fp; WSADATA wsadata; ret = WSAStartup(MAKEWORD(2,0), &wsadata); if (ret != 0) { fprintf(stderr, "WSAStartup failed with error: %d\n", ret); return 1; } ret = libssh2_init (0); if (ret != 0) { fprintf (stderr, "libssh2 initialization failed (%d)\n", ret); return 1; } sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); //SFTP默认端口为22端口 sin.sin_addr.S_un.S_addr = inet_addr(HOST); if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "failed to connect!\n"); return -1; } session = libssh2_session_init(); //创建一个session if (!session) return -1; libssh2_session_set_blocking(session, 0); //设置为非阻塞方式 while ((ret = libssh2_session_handshake(session, sock)) == LIBSSH2_ERROR_EAGAIN) //创建一个SSH session ; if (ret) { fprintf(stderr, "Failure establishing SSH session: %d\n", ret); return -1; } //到这里我们还没有权限访问,所以接下来要做的是检查hostkey's finger fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); fprintf(stderr, "Fingerprint: "); for(i = 0; i < 20; i++) { fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); } fprintf(stderr, "\n"); //只是用密码进行验证 while ((ret = libssh2_userauth_password(session, USER, PWD)) == LIBSSH2_ERROR_EAGAIN) ; if (ret) { fprintf(stderr, "Authentication by password failed.\n"); goto shutdown2; } fprintf(stderr, "libssh2_sftp_init()!\n"); do { sftp_session = libssh2_sftp_init(session); if(!sftp_session) { if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { fprintf(stderr, "non-blocking init\n"); waitsocket(sock, session); /* now we wait */ } else { fprintf(stderr, "Unable to init SFTP session\n"); goto shutdown2; } } } while (!sftp_session); fprintf(stderr, "libssh2_sftp_open()!\n"); //请求一个文件,通过ssh方式 do { sftp_handle = libssh2_sftp_open(sftp_session, FILENAME, LIBSSH2_FXF_READ, 0); if (!sftp_handle) { if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) { fprintf(stderr, "Unable to open file with SFTP\n"); goto shutdown2; } else { fprintf(stderr, "non-blocking open\n"); waitsocket(sock, session); /* now we wait */ } } } while (!sftp_handle); gettimeofday(&start,NULL); //打开文件进行保存 fp = fopen(LOCLFILE,"wb"); if(fp==NULL) { fprintf(stderr,"Can't open local file %s\n",LOCLFILE); return -1; } fprintf(stderr, "libssh2_sftp_open() is done, now receive data!\n"); do { char mem[1024*24]; /* loop until we fail */ while ((ret = libssh2_sftp_read(sftp_handle, mem, sizeof(mem))) == LIBSSH2_ERROR_EAGAIN) { spin++; waitsocket(sock, session); /* now we wait */ } if (ret > 0) { total += ret; //write(1, mem, ret); fwrite(mem,1,ret,fp); //写入到文件中 } else { break; } } while (1); fclose(fp); gettimeofday(&end,NULL); time_ms = tvdiff(end, start); //打印传输速率 fprintf(stderr, "Got %.4lf Mbytes in %.2lf sec = %.4lf Kbytes/sec spin: %d\n", total/1024.0/1024.0, time_ms/1000.0, total/((time_ms+1)/1000.0)/1024/1024, spin ); libssh2_sftp_close(sftp_handle); libssh2_sftp_shutdown(sftp_session); rc = 0;//执行到改行代码表示已经正常下载文件 shutdown2: fprintf(stderr, "libssh2_session_disconnect\n"); while (libssh2_session_disconnect(session, "Normal Shutdown, Thank you") == LIBSSH2_ERROR_EAGAIN) ; libssh2_session_free(session); closesocket(sock); fprintf(stderr, "all done\n"); libssh2_exit(); return rc; } long tvdiff(struct timeval newer, struct timeval older) { return (newer.tv_sec-older.tv_sec)*1000+(newer.tv_usec-older.tv_usec)/1000; } int waitsocket(int socket_fd, LIBSSH2_SESSION *session) { struct timeval timeout; int ret; fd_set fd; fd_set *writefd = NULL; fd_set *readfd = NULL; int dir; timeout.tv_sec = 10; timeout.tv_usec = 0; FD_ZERO(&fd); FD_SET(socket_fd, &fd); /* now make sure we wait in the correct direction */ dir = libssh2_session_block_directions(session); if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) readfd = &fd; if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) writefd = &fd; ret = select(socket_fd + 1, readfd, writefd, NULL, &timeout); return ret; }
View Code
至于用到的libssh2_config.h这个文件,没有的话可以在代码中注释掉.
下面这个是freesshd产生的日志中一部分
05-28-2015 14:18:05 HOST localhost SSH connection attempt. 05-28-2015 14:18:05 HOST localhost SSH user successfully logged on using password. 05-28-2015 14:18:06 SFTP service granted to user user. 05-28-2015 14:18:06 HOST localhost user is uploading wunaozai.txt (E:\wunaozai.txt) 05-28-2015 14:18:06 HOST localhost SSH user disconnected. 05-28-2015 14:18:23 HOST localhost SSH connection attempt. 05-28-2015 14:18:23 HOST localhost SSH user successfully logged on using password. 05-28-2015 14:18:23 SFTP service granted to user user. 05-28-2015 14:18:23 HOST localhost user is uploading wunaozai.txt (E:\wunaozai.txt) 05-28-2015 14:18:23 HOST localhost SSH user disconnected. 05-28-2015 14:18:49 HOST localhost SSH connection attempt. 05-28-2015 14:18:49 HOST localhost SSH user successfully logged on using password. 05-28-2015 14:18:49 SFTP service granted to user user. 05-28-2015 14:18:49 HOST localhost user is uploading wunaozai.txt (E:\wunaozai.txt) 05-28-2015 14:18:49 HOST localhost SSH user disconnected. 05-28-2015 14:18:55 HOST localhost SSH connection attempt. 05-28-2015 14:18:56 HOST localhost SSH user successfully logged on using password. 05-28-2015 14:18:56 SFTP service granted to user user. 05-28-2015 14:18:56 HOST localhost user is downloading wunaozai.txt (E:\wunaozai.txt) 05-28-2015 14:18:56 HOST localhost SSH user disconnected.
有了上面这两个主要的功能,SFTP的客户端就基本功能实现了,至于mkdir和dir功能就参考里面的示例程序,基本都可以看懂。
3.使用putty连接freesshd
了解过SFTP原理之后,就知道,SFTP其实跟FTP没有多大的关系,其实就是一个使用SSH协议,然后进行会话,会话过程保存为文件,嗯,大概就是这个样子了。所以我们可以使用普通的ssh软件进行登录,拿到该SFTP服务器站点的SHELL。然后可以各种操作,看起来很危险的样子,所以不管用什么SFTP服务器在配置用户的时候要注意的。 putty工具里面还有个PSFTP.exe这个工具可以连接到SFTP服务器,没事的也可以玩玩看。
本文地址: /article/6193159.html
相关文章推荐
- 网络编程(4)—— 基于Windows系统的socket客户端的编程步骤
- Socket网络编程--FTP客户端(60篇socket博客,而且都比较简单、深入浅出)
- 网络编程_TCP_Socket通信_聊天室_客户端多线程_群聊JAVA191-192
- Java网络编程下之Socket客户端编程
- iOS网络编程实践--NSStream实现TCP Socket iPhone客户端
- iOS网络编程之Socket(客户端)
- socket网络编程--基于windows
- 【.Net MF网络开发板研究-05】Socket编程之客户端
- java:网络编程(一/基于Socket的单客户端连接)
- Socket、TCP/IP、HTTP、FTP及网络编程
- Python网络编程之socket编程(一)--使用TCP和UDP客户端和服务器通信
- windows网络编程之socket中的非阻塞connect()与getsockopt()
- 网络编程--ftp客户端的实现(c#版)
- Windows网络编程之面向连接的Socket编程
- 【.Net MF网络开发板研究-05】Socket编程之客户端 推荐
- 网络编程二(套接字Socket、客户端和服务端通信问题)
- ftp客户端源代码,使用VC+SOCKET编程,在SERV-U6.0服务器上测试通过,能断点续传
- 【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信
- Socket网络编程 客户端与服务端通信流程