FtpServerDlg.cpp
上传用户:shjunxiao
上传日期:2022-01-25
资源大小:7105k
文件大小:9k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // FtpServerDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "FtpServer.h"
  5. #include "FtpServerDlg.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CAboutDlg dialog used for App About
  13. static int BUFSIZE = 2000;//文件分块的大小,以字节算
  14. typedef enum {FILEPACKET}PacketType;
  15. //文件分块的结构
  16. typedef struct{
  17. PacketType packetType;//块类型:文件块
  18. char szFileName[256];//文件名
  19. long nIndex;//文件块的序号
  20. long nCount;//文件分块的个数
  21. char content[2001];//存储单个文件块内容
  22. unsigned int length;//单个文件块内容的长度
  23. }DATA_PACKET;
  24. CRITICAL_SECTION CriticalSection;//多线程同步用到的创建互斥对象需要的
  25. typedef struct tagSubPack
  26. {
  27. SOCKET socket;//套接字
  28. fd_set fdSocket;//套接字集,即SOCKET数组
  29. }SubPack;
  30. char szPath[256] = { 0 };//服务器端保存文件的路径
  31. class CAboutDlg : public CDialog
  32. {
  33. public:
  34. CAboutDlg();
  35. // Dialog Data
  36. //{{AFX_DATA(CAboutDlg)
  37. enum { IDD = IDD_ABOUTBOX };
  38. //}}AFX_DATA
  39. // ClassWizard generated virtual function overrides
  40. //{{AFX_VIRTUAL(CAboutDlg)
  41. protected:
  42. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  43. //}}AFX_VIRTUAL
  44. // Implementation
  45. protected:
  46. //{{AFX_MSG(CAboutDlg)
  47. //}}AFX_MSG
  48. DECLARE_MESSAGE_MAP()
  49. };
  50. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  51. {
  52. //{{AFX_DATA_INIT(CAboutDlg)
  53. //}}AFX_DATA_INIT
  54. }
  55. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  56. {
  57. CDialog::DoDataExchange(pDX);
  58. //{{AFX_DATA_MAP(CAboutDlg)
  59. //}}AFX_DATA_MAP
  60. }
  61. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  62. //{{AFX_MSG_MAP(CAboutDlg)
  63. // No message handlers
  64. //}}AFX_MSG_MAP
  65. END_MESSAGE_MAP()
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CFtpServerDlg dialog
  68. CFtpServerDlg::CFtpServerDlg(CWnd* pParent /*=NULL*/)
  69. : CDialog(CFtpServerDlg::IDD, pParent)
  70. {
  71. //{{AFX_DATA_INIT(CFtpServerDlg)
  72. m_port = _T("8888");
  73. m_mulu = _T("D:\ftp\");
  74. //}}AFX_DATA_INIT
  75. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  76. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  77. }
  78. void CFtpServerDlg::DoDataExchange(CDataExchange* pDX)
  79. {
  80. CDialog::DoDataExchange(pDX);
  81. //{{AFX_DATA_MAP(CFtpServerDlg)
  82. DDX_Control(pDX, IDC_START, m_start);
  83. DDX_Text(pDX, IDC_EDIT_PORT, m_port);
  84. DDX_Text(pDX, IDC_EDIT_MULU, m_mulu);
  85. //}}AFX_DATA_MAP
  86. }
  87. BEGIN_MESSAGE_MAP(CFtpServerDlg, CDialog)
  88. //{{AFX_MSG_MAP(CFtpServerDlg)
  89. ON_WM_SYSCOMMAND()
  90. ON_WM_PAINT()
  91. ON_WM_QUERYDRAGICON()
  92. ON_BN_CLICKED(IDC_START, OnStart)
  93. //}}AFX_MSG_MAP
  94. END_MESSAGE_MAP()
  95. /////////////////////////////////////////////////////////////////////////////
  96. // CFtpServerDlg message handlers
  97. BOOL CFtpServerDlg::OnInitDialog()
  98. {
  99. CDialog::OnInitDialog();
  100. // Add "About..." menu item to system menu.
  101. // IDM_ABOUTBOX must be in the system command range.
  102. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  103. ASSERT(IDM_ABOUTBOX < 0xF000);
  104. CMenu* pSysMenu = GetSystemMenu(FALSE);
  105. if (pSysMenu != NULL)
  106. {
  107. CString strAboutMenu;
  108. strAboutMenu.LoadString(IDS_ABOUTBOX);
  109. if (!strAboutMenu.IsEmpty())
  110. {
  111. pSysMenu->AppendMenu(MF_SEPARATOR);
  112. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  113. }
  114. }
  115. // Set the icon for this dialog.  The framework does this automatically
  116. //  when the application's main window is not a dialog
  117. SetIcon(m_hIcon, TRUE); // Set big icon
  118. SetIcon(m_hIcon, FALSE); // Set small icon
  119. // TODO: Add extra initialization here
  120. m_sock = INVALID_SOCKET;
  121. strcpy(szPath,m_mulu);
  122. return TRUE;  // return TRUE  unless you set the focus to a control
  123. }
  124. void CFtpServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
  125. {
  126. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  127. {
  128. CAboutDlg dlgAbout;
  129. dlgAbout.DoModal();
  130. }
  131. else
  132. {
  133. CDialog::OnSysCommand(nID, lParam);
  134. }
  135. }
  136. // If you add a minimize button to your dialog, you will need the code below
  137. //  to draw the icon.  For MFC applications using the document/view model,
  138. //  this is automatically done for you by the framework.
  139. void CFtpServerDlg::OnPaint() 
  140. {
  141. if (IsIconic())
  142. {
  143. CPaintDC dc(this); // device context for painting
  144. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  145. // Center icon in client rectangle
  146. int cxIcon = GetSystemMetrics(SM_CXICON);
  147. int cyIcon = GetSystemMetrics(SM_CYICON);
  148. CRect rect;
  149. GetClientRect(&rect);
  150. int x = (rect.Width() - cxIcon + 1) / 2;
  151. int y = (rect.Height() - cyIcon + 1) / 2;
  152. // Draw the icon
  153. dc.DrawIcon(x, y, m_hIcon);
  154. }
  155. else
  156. {
  157. CDialog::OnPaint();
  158. }
  159. }
  160. // The system calls this to obtain the cursor to display while the user drags
  161. //  the minimized window.
  162. HCURSOR CFtpServerDlg::OnQueryDragIcon()
  163. {
  164. return (HCURSOR) m_hIcon;
  165. }
  166. //启动服务
  167. void CFtpServerDlg::OnStart() 
  168. {
  169. // TODO: Add your control notification handler code here
  170. InitializeCriticalSection(&CriticalSection);//多线程要用到的互斥对象创建,同步的
  171. //进入监听状态
  172. InitSocket();
  173. DWORD dwThread;
  174. HANDLE hThread = CreateThread(NULL, 0, RecvProc, (LPVOID)m_sock, 0, &dwThread);
  175. WaitForSingleObject(hThread, INFINITE);//INFINITE表示一直休息。。。直到新的线程请求
  176. DWORD ExitCode;
  177. GetExitCodeThread(hThread, &ExitCode);
  178. ExitThread(ExitCode);
  179. }
  180. //初始化套结字
  181. BOOL CFtpServerDlg::InitSocket()
  182. {
  183. if(m_sock == INVALID_SOCKET)
  184. {
  185. m_sock = socket(AF_INET,SOCK_STREAM ,0);
  186. }
  187. if(INVALID_SOCKET  == m_sock)
  188. {
  189. MessageBox("创建套接字失败!");
  190. return FALSE;
  191. }
  192. CString sPort;
  193. GetDlgItem(IDC_EDIT_PORT)->GetWindowText(sPort);
  194. //MessageBox("开启的端口:"+sPort);
  195. int nPort = atoi(sPort);
  196. if(nPort < 1 || nPort > 65535)
  197. {
  198. MessageBox("端口号错误!");
  199. return FALSE;
  200. }
  201. SOCKADDR_IN srvAddr;
  202. srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  203. srvAddr.sin_family = AF_INET;
  204. srvAddr.sin_port = htons(nPort);
  205. if(bind(m_sock,(SOCKADDR*)&srvAddr,sizeof(SOCKADDR))== SOCKET_ERROR)
  206. {
  207. closesocket(m_sock);
  208. MessageBox("绑定套接字失败!");
  209. return FALSE;
  210. }
  211. int m_nClient = listen(m_sock,5);
  212. if(m_nClient != 0)
  213. {
  214. MessageBox("Listen error!");
  215. closesocket(m_sock);
  216. return FALSE;
  217. }
  218. MessageBox("Success");
  219. return TRUE;
  220. }
  221. void CFtpServerDlg::CloseAllSocket()
  222. {
  223. // 关闭监听套节字
  224. if(m_sock != INVALID_SOCKET)
  225. {
  226. closesocket(m_sock);
  227. m_sock = INVALID_SOCKET;
  228. }
  229. }
  230. DWORD WINAPI CFtpServerDlg::SubRecvProc(LPVOID lpParameter)
  231. {
  232. SOCKET socket = ((SubPack *)lpParameter)->socket;
  233. DATA_PACKET recvPacket;
  234. char szTemp[24000] = { 0 };
  235. int nRecev=recv(socket, szTemp, //(char*)&recvPacket,
  236. 24000,0);
  237. int  nPreIndex = 0;
  238. FILE *file = 0;
  239. if (nRecev > 0)
  240. {
  241. memcpy(&recvPacket, szTemp, sizeof(DATA_PACKET));
  242. char szFile[256] = { 0 };
  243. sprintf(szFile, "%s%s", szPath, recvPacket.szFileName);
  244. file  = fopen( szFile, "wb" );
  245. }
  246. while(nRecev>0)
  247. {
  248. send(socket, (char*)"RECV_END",sizeof("RECV_END"),0 );
  249. for (unsigned int i = 0; i<nRecev/sizeof(DATA_PACKET); i++)
  250. {
  251. memset(&recvPacket, 0, sizeof(DATA_PACKET));
  252. memcpy(&recvPacket, szTemp + i * sizeof(DATA_PACKET), sizeof(DATA_PACKET));
  253. if (recvPacket.packetType == FILEPACKET)
  254. {
  255. fseek(file,(recvPacket.nIndex-1)*BUFSIZE,SEEK_SET );
  256. int errorcode=fwrite( recvPacket.content,1,recvPacket.length,file );
  257. fflush(file);
  258. }
  259. }
  260. memset(szTemp, 0, 24000);
  261. nRecev = recv(socket, szTemp, 24000,0);
  262. }
  263. if(file)
  264. fclose(file);
  265. return 0;
  266. }
  267. DWORD WINAPI CFtpServerDlg::RecvProc(LPVOID lpParameter)
  268. {
  269. SOCKET socket = (SOCKET)lpParameter;
  270. fd_set fdSocket;
  271. FD_ZERO(&fdSocket);
  272. FD_SET(socket,&fdSocket);
  273. timeval timeout;//这个结构体用于select函数,用于多线程中同步互斥时间间隔
  274. timeout.tv_sec=5;//5秒
  275. CRITICAL_SECTION CriticalSection;
  276. InitializeCriticalSection(&CriticalSection );
  277. while(true)
  278. {
  279. fd_set fdRead=fdSocket;
  280. int nRet=select(0,&fdRead,NULL,NULL,NULL);//Sockets select函数决定一个或多个socket的状态, 
  281. //最后一个参数可以是timeout中具体设置的值,为空就直到一个请求到
  282. //来前一直等待。。。
  283. if(nRet>0)
  284. {
  285. for(int i=0;i<(int)fdSocket.fd_count;i++)
  286. { if(FD_ISSET(fdSocket.fd_array[i],&fdRead))
  287. {
  288. if(fdSocket.fd_array[i]==socket)
  289. {
  290. char szClientIP[128] = {  0 };
  291. sockaddr_in addrRemote;
  292. int nAddrLen=sizeof(addrRemote);
  293. SOCKET sNew=accept(socket,(sockaddr*)&addrRemote,&nAddrLen);//接收客户端的连接
  294. FD_SET(sNew,&fdSocket);//加入新的套接字进入套接字集
  295. sprintf( szClientIP, "%s",inet_ntoa(addrRemote.sin_addr) );
  296. }
  297. else
  298. {
  299. SubPack subpack;
  300. subpack.socket = fdSocket.fd_array[i];
  301. subpack.fdSocket = fdSocket;
  302. DWORD dwThread;
  303. HANDLE hThread = CreateThread(NULL, 0, SubRecvProc, (LPVOID)&subpack, 0, &dwThread);
  304. WaitForSingleObject(hThread, INFINITE);
  305. closesocket(fdSocket.fd_array[i]);
  306. FD_CLR(fdSocket.fd_array[i],&fdSocket);
  307. }
  308. }
  309. }
  310. }
  311. }
  312. return 0;
  313. }