C++ socket实现miniFTP

2020-01-06 16:00:22王冬梅

main.cpp


#define _CRT_SECURE_NO_WARNINGS 
#define _WINSOCK_DEPRECATED_NO_WARNINGS 
#pragma(lib,"ws2_32.lib") 
#include"ftpClient.h" 
#include<stdio.h> 
 
int main() 
{ 
  ftpClient a; 
  a.start(); 
  return 0; 
} 

ftpServer.h


#pragma once 
#include<winsock.h> 
 
class ftpServer 
{ 
private: 
  enum { 
    SERVER_PORT = 9999, 
    BUFFER_SIZE = 4096, 
    QUEUE_SIZE = 10 
  }; 
  char buffer[BUFFER_SIZE]; 
  sockaddr_in serverChannel; 
  char name[50]; 
  char workDir[100]; //store like C:Users MARK:字符串末没有斜线!! 
  int serverSocket; //socket 
  int clientSocket; 
  bool sendFile(); 
  bool receiveFile(); 
  bool doPwd(); 
  bool doCd(); 
  bool isValidPath(char* path); 
public: 
  ftpServer(); 
  bool start();//开启服务器 
}; 

ftpServer.cpp

 


#define _CRT_SECURE_NO_WARNINGS 
 
#include"ftpServer.h" 
#include<cstdio> 
#include<cstdlib> 
#include<fstream> 
#include<cstring> 
 
ftpServer::ftpServer() 
{ 
  WORD wVersionRequested; 
  WSADATA wsaData; 
  int ret; 
 
  //WinSock初始化: 
  wVersionRequested = MAKEWORD(2, 2);//希望使用的WinSock DLL的版本 
  ret = WSAStartup(wVersionRequested, &wsaData); 
  if (ret != 0) 
  { 
    printf("WSAStartup() failed!n"); 
  } 
  //确认WinSock DLL支持版本2.2: 
  if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
  { 
    WSACleanup(); 
    printf("Invalid Winsock version!n"); 
  } 
  //workDir初始化为当前路径 
  system("cd > tempFile"); 
  std::ifstream in("tempFile", std::ifstream::in); 
  in >> workDir; 
  in.close(); 
} 
 
bool ftpServer::start() 
{ 
  int on = 1; 
 
  //初始化服务器 
  memset(&serverChannel, 0, sizeof(serverChannel)); 
  serverChannel.sin_family = AF_INET; 
  serverChannel.sin_addr.s_addr = htonl(INADDR_ANY); 
  serverChannel.sin_port = htons(SERVER_PORT); 
 
  //创建套接字 
  this->serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
  if (serverSocket < 0) { 
    printf("cannot create socketn"); 
    return false; 
  } 
  else printf("successfully create socketn"); 
  setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, 
    (char*)&on, sizeof(on)); 
 
  //绑定 
  int b = bind(serverSocket, (sockaddr*)&serverChannel, 
    sizeof(serverChannel)); 
  if (b < 0) { 
    printf("bind errorn"); 
    return false; 
  } 
  else printf("successfully bindn"); 
  //监听 
  int l = listen(serverSocket, QUEUE_SIZE); 
  if (l < 0) { 
    printf("listen failedn"); 
    return false; 
  } 
  else printf("successfully listenn"); 
  int len = sizeof(serverChannel); 
  //服务器等待连接 
  while (1) { 
    printf("waiting for connection...n"); 
    //接受一个连接 
    clientSocket = accept(serverSocket, (sockaddr*)&serverChannel, 
      &len); 
    if (clientSocket < 0) { 
      printf("accept failedn"); 
    } 
    else { 
      printf("successfully connectn"); 
      while (1) { 
        memset(buffer, 0, sizeof(buffer)); 
        int ret; 
 
        ret = recv(clientSocket, buffer, BUFFER_SIZE, 0); 
 
        if (ret == SOCKET_ERROR) { 
          printf("receive failedn"); 
        } 
        else { 
          char opt[50]; 
          printf("successfully receiven"); 
          int i = 0, j = 0; 
          printf("buffer = %sn", buffer); 
          while (buffer[i] != ' '&&buffer[i] != '') { 
            opt[i] = buffer[i]; 
            i++; 
          } 
          opt[i] = ''; 
          if (buffer[i] != '') { 
            i++; 
          } 
          while (buffer[i] != '') { 
            name[j] = buffer[i]; 
            i++, j++; 
          } 
          name[j] = ''; 
 
          if (strcmp(opt, "get") == 0) { 
            char ret[4]; 
            if (!sendFile()) { 
              strcpy(ret, "NAK"); 
              send(clientSocket, ret, sizeof(ret), 0); 
            } 
            else { 
              strcpy(ret, "ACK"); 
              send(clientSocket, ret, sizeof(ret), 0); 
            } 
          } 
          else if (strcmp(opt, "put") == 0) { 
            receiveFile(); 
          } 
          else if (strcmp(opt, "pwd") == 0) { 
            doPwd(); 
          } 
          else if (strcmp(opt, "cd") == 0) { 
            doCd(); 
          } 
          else if (strcmp(opt, "close") == 0) { 
            break; 
          } 
          else { 
            printf("syntex errorn"); 
          } 
        } 
      } 
    } 
  } 
  return true; 
} 
 
bool ftpServer::sendFile() 
{ 
  std::ifstream in; 
  char path[100]; 
  strcpy(path, workDir); 
  strcat(path, ""); 
  strcat(path, name); 
 
  in.open(path, std::ios::binary); 
  if (!in) { 
    printf("cannot open the filen"); 
    return false; 
  } 
  memset(buffer, 0, sizeof(buffer)); 
  in.seekg(0, std::ios_base::end); 
  int sp = in.tellg(); 
  int total_size = 0; 
  int r; 
  char length[20]; 
  sprintf(length, "%d", sp); 
   
  r = send(clientSocket, length, sizeof(length), 0); 
 
  if (r == SOCKET_ERROR) { 
    printf("send failedn"); 
    return false; 
  } 
  else { 
    printf("send successn"); 
  } 
 
  while (sp > 0) { 
    in.clear(); 
    in.seekg(total_size, std::ios_base::beg); 
    memset(buffer, 0, sizeof(buffer)); 
    in.read(buffer, sizeof(buffer)); 
    int size = sp < BUFFER_SIZE ? sp : BUFFER_SIZE; 
    total_size += size; 
    r = send(clientSocket, buffer, size, 0); 
 
    sp -= size; 
    if (r == SOCKET_ERROR) { 
      printf("send failedn"); 
      return false; 
    } 
    else { 
      printf("send successn"); 
    } 
  } 
  in.close(); 
  return true; 
} 
 
bool ftpServer::receiveFile() 
{ 
  char path[100]; 
  strcpy(path, workDir); 
  strcat(path, ""); 
  strcat(path, name); 
  memset(buffer, 0, sizeof(buffer)); 
  int ret; 
  char length[20]; 
  ret = recv(clientSocket, length, sizeof(length), 0); 
  if (ret == SOCKET_ERROR) { 
    printf("receive failedn"); 
    return false; 
  } 
  else { 
    printf("successfully receiven"); 
  } 
  int size = atoi(length); 
  std::ofstream out; 
 
  out.open(path, std::ios::binary); 
  if (!out) { 
    printf("cannot save the filen"); 
    return false; 
  } 
  while (size>0) { 
    int s = size < BUFFER_SIZE ? size : BUFFER_SIZE; 
    ret = recv(clientSocket, buffer, BUFFER_SIZE, 0); 
    if (ret == SOCKET_ERROR) { 
      printf("receive failedn"); 
      break; 
    } 
    else { 
      printf("successfully receiven"); 
      out.write(buffer, s); 
    } 
    size -= BUFFER_SIZE; 
  } 
  out.close(); 
  return true; 
} 
 
bool ftpServer::doPwd() { 
  char temCMD[150]; 
  memset(temCMD, 0, sizeof(temCMD)); 
  strcat(temCMD, "echo "); 
  strcat(temCMD, workDir); 
  strcat(temCMD, " > tempFile"); 
  system(temCMD); 
  memset(temCMD, 0, sizeof(temCMD)); 
  strcat(temCMD, "dir /b "); 
  strcat(temCMD, workDir); 
  strcat(temCMD, " >> tempFile"); 
  system(temCMD); 
 
  std::ifstream in("tempFile", std::fstream::in); 
  if (!in) { 
    printf("cannot open the filen"); 
    return false; 
  } 
  memset(buffer, 0, sizeof(buffer)); 
  in.seekg(0, std::ios_base::end); 
  int sp = in.tellg(); 
  int total_size = 0; 
  int r; 
  char length[20]; 
  sprintf(length, "%d", sp); 
  r = send(clientSocket, length, sizeof(length), 0); 
 
  if (r == SOCKET_ERROR) { 
    printf("send failedn"); 
    return false; 
  } 
  else { 
    printf("send successn"); 
  } 
  while (sp > 0) { 
    in.clear(); 
    in.seekg(total_size, std::ios_base::beg); 
    memset(buffer, 0, sizeof(buffer)); 
    in.read(buffer, sizeof(buffer)); 
    int size = sp < BUFFER_SIZE ? sp : BUFFER_SIZE; 
    total_size += size; 
    printf("transfer size = %dn", total_size); 
    r = send(clientSocket, buffer, size, 0); 
 
    sp -= size; 
    if (r == SOCKET_ERROR) { 
      printf("send failedn"); 
      return false; 
    } 
    else { 
      printf("send successn"); 
    } 
  } 
  in.close(); 
  return true; 
} 
 
bool ftpServer::isValidPath(char* path) { 
  char temCMD[100]; 
  memset(temCMD, 0, sizeof(temCMD)); 
  strcat(temCMD, "cd "); 
  strcat(temCMD, path); 
  int res = system(temCMD); 
  return res == 0; 
} 
 
bool ftpServer::doCd() { 
  for (int i = 0; name[i] != ''; ++i) { 
    if (name[i] == '/') 
      name[i] = ''; 
  } 
  if (name[0] == '.'&&name[1] == '.') { 
    char temDir[100]; 
    strcpy(temDir, workDir); 
    for (int i = sizeof(temDir); i >= 0; --i) { 
      if (temDir[i] == '') { 
        temDir[i] = ''; 
        break; 
      } 
    } 
    strcat(temDir, name + 2); 
    if (isValidPath(temDir)) { 
      strcpy(workDir, temDir); 
    } 
    else { 
      return false; 
    } 
  } 
  else if (name[0] == '.'&&name[1] != '.') { 
    char temDir[100]; 
    strcpy(temDir, workDir); 
    strcat(temDir, name + 1); 
    if (isValidPath(temDir)) { 
      strcpy(workDir, temDir); 
    } 
    else { 
      return false; 
    } 
  } 
  else if (name[1] == ':') { 
    if (isValidPath(name)) { 
      strcpy(workDir, name); 
    } 
    else { 
      return false; 
    } 
  } 
  else { 
    char temDir[100]; 
    strcpy(temDir, workDir); 
    strcat(temDir, ""); 
    strcat(temDir, name); 
    if (isValidPath(temDir)) { 
      strcpy(workDir, temDir); 
    } 
    else { 
      return false; 
    } 
  } 
  return true; 
}