C + + Socket implementation Miniftp_c language

Source: Internet
Author: User

The example of this article for everyone to share the C + + socket to achieve Miniftp method for your reference, the specific content as follows

Client:

Service side:

Establish a connection

The connection uses a TCP connection, the server and the client create their own sockets, the server waits for the connection, and the client initiates the connection (and specifies the server IP). In the case where the port number is consistent and not occupied, the connection is established.
Throughout the process, the server establishes a connection to each visiting client, which persists when the customer has not requested to disconnect from the server, and the user can keep making requests to the server. (Persistent, pipelined connection)
When the client is disconnected, the socket portion of the client is closed and the server continues to wait for the new connection. The server can only handle a single client connection at a time and does not support concurrent access.

PDU format

Since FTP should support almost any type of file, and almost all types of files can be parsed using binary, we use a binary format to read and write files. Throughout the process, we don't care about the specifics of the file, we don't need to parse the file in the program, we treat it as a data stream.
Limited by the size of the buffer, we can not transfer the entire file at a time, so we will be divided into the buffer size of the file into the packet sent in batches, we can data from the buffer to write files in a timely manner, so that the buffer space. The packet contains only data and does not contain header or tail information.
In addition, when receiving files, the recv () function will loop, so we need a signal to tell when the delivery is complete.
One idea is to send a termination signal, which is feasible, but a better approach is to send the total number of bytes at the beginning, allowing the receiver to determine when the receiver is finished based on the size of the remaining bytes. Because when we write a file, we need to specify the number of bytes written, especially if the number of bytes in the stream is not equal to the buffer size. Errors written to the byte number cause the file to be corrupted.

Receive Confirmation

We know that TCP is a reliable transport protocol, and it takes a series of measures to ensure that the transmission does not go wrong. So when using a TCP connection, we believe that the data does not go wrong on the link layer and that it will be successfully sent to the other person's hand. But when the client receives the file from the server, we still need to send the server to confirm the information. The reason is that although we can guarantee that the link layer is not wrong, we cannot guarantee that the application layer is not faulted. For example, the client might give the wrong filename because it would not receive information from the server, so it would be in a null state.

FtpClient.h

#pragma  
#include <winsock.h> 
class ftpclient 
{ 
private: 
  enum { 
    server_port = 9999, 
    buffer_size = 4096 
  }; 
  Sockaddr_in Serverchannel; 
  Char buffer[buffer_size]; 
  int serversocket; 
  int clientsocket; 
  BOOL Isconnect; 
  Char name[50]; 
 
  BOOL GetFile (); 
  BOOL Putfile (); 
  bool Acknowledge (); 
  BOOL SendRequest (char* instruction); 
  BOOL Connect2host (const char* hostName); 
  BOOL Getworkdir (); 
 
Public: 
  ftpclient (); 
  ~ftpclient (); 
  void start (); 
 

FtpClient.cpp

#define _crt_secure_no_warnings #include "ftpClient.h" #include <cstdio> #include <io.h> #include < 
  cstring> #include <fstream> ftpclient::ftpclient () {WORD wversionrequested; 
  Wsadata Wsadata; 
 
  int ret; Winsock Initialization: wversionrequested = Makeword (2, 2);//The version of the Winsock DLL that you want to use RET = WSAStartup (wversionrequested, &wsad 
  ATA); 
  if (ret!= 0) {printf ("WSAStartup () failed!\n"); }//Confirm Winsock DLL support version 2.2:if (Lobyte (wsadata.wversion)!= 2 | | 
    Hibyte (wsadata.wversion)!= 2) {wsacleanup (); 
  printf ("Invalid Winsock version!\n"); 
} Isconnect = false; 
  } void Ftpclient::start () {char c[100]; 
  Char d[100]; 
 
  printf ("Here is the FTP client, you can enter help to view the action method, enter quit to exit the client \ n"); 
    while (1) {scanf ("%s", c); if (strcmp (c, "help") = = 0) {printf ("get [filename]--download file \ n" "Put [fileName]--upload file \ n" "F TP [IP]--Login ftp\n "" pwd--Display the server's current working folder \ n "" CD [DirnaMe]--Change the current folder \ n "" Close--turn off connection to current FTP \ n "" Quit--exit client \ n "); 
      else if (strcmp (c, "get") = = 0) {scanf ("%s", d); 
      Strcat (C, ""); 
      Strcat (c, D); 
      if (!isconnect) {printf ("You haven ' t connected to any server!\n"); 
    else SendRequest (c); 
      else if (strcmp (c, "put") = = 0) {scanf ("%s", d); 
      Strcat (C, ""); 
      Strcat (c, D); 
      if (!isconnect) {printf ("You haven ' t connected to any server!\n"); 
    else SendRequest (c); 
      else if (strcmp (C, "ftp") = = 0) {scanf ("%s", d); 
      if (!isconnect&&connect2host (d)) {isconnect = true; else if (isconnect) {printf ("You have already connected to server\n" " 
      Ion before connect to a new server\n "); } else if (strcmp (c, "pwd") = = 0) {if (!isconnect) {printf ("You haven ' tConnected to any server!\n "); 
    else SendRequest (c); 
      else if (strcmp (C, "cd") = = 0) {scanf ("%s", d); 
      Strcat (C, ""); 
      Strcat (c, D); 
      if (!isconnect) {printf ("You haven ' t connected to any server!\n"); 
    else SendRequest (c); 
        else if (strcmp (c, "quit") = = 0) {if (isconnect) {strcpy (c, "close"); 
        Isconnect = false; 
        Send (Clientsocket, C, strlen (c) + 1, 0); 
      Closesocket (Clientsocket); 
    } break; 
        else if (strcmp (c, "close") = = 0) {if (isconnect) {isconnect = false; 
        Send (Clientsocket, C, strlen (c) + 1, 0); 
      Closesocket (Clientsocket); 
    } else {printf ("Syntex error\n"); } bool Ftpclient::connect2host (const char* hostName) {//create socket Clientsocket = socket (Af_inet, Sock_st 
 
  Ream, IPPROTO_TCP); if (Clientsocket < 0) {printf ("Cannot create socket\n"); 
  return false; 
  else printf ("successfully create socket\n"); memset (&serverchannel, 0, sizeof (serverchannel));//initialized to 0 serverchannel.sin_family = Af_inet;//channel protocol Family af_ INET serverchannel.sin_addr. S_un.  
  S_ADDR = inet_addr (hostName);//Address Serverchannel.sin_port = htons (server_port);//server port//Establish connection 
 
  ServerSocket = Connect (Clientsocket, (sockaddr*) &serverchannel, sizeof (Serverchannel)); 
    if (ServerSocket < 0) {printf ("Cannot connect to the host\n"); 
  return false; 
    else {printf ("Successfully connect to the host\n"); 
  return true;  } bool Ftpclient::sendrequest (char* instruction) {int r = Send (clientsocket, instruction, strlen (instruction) + 
  1, 0); 
    if (r = = socket_error) {printf ("Request failed\n"); 
  return false; 
    else {printf ("Request success\n"); 
    Char opt[5]; 
    int i = 0, j = 0; while (Instruction[i]!= ' &&instruction[i]!= ' ") {
      Opt[i] = Instruction[i]; 
    i++; 
    } Opt[i] = '; 
    i++; 
      while (Instruction[i]!= ' ") {name[j] = Instruction[i]; 
    i++, j + +; 
    } Name[j] = '; 
      if (strcmp (OPT, "get") = = 0) {if (GetFile ()) {printf ("successfully download\n"); 
    else printf ("Download failed\n"); 
      else if (strcmp (OPT, "put") = = 0) {if (Putfile ()) {printf ("successfully upload\n"); 
    else printf ("Upload failed\n"); 
    else if (strcmp (OPT, "pwd") = = 0) {if (!getworkdir ()) printf ("Get Work Directory failed\n"); 
    else if (strcmp (OPT, "cd") = = 0) {printf ("Operation Finished\n"); 
      else {printf ("Syntex error\n"); 
    return false; 
  return true; 
  } bool Ftpclient::getfile () {memset (buffer, 0, sizeof (buffer)); 
  int ret; 
  Char length[20]; 
  ret = recv (clientsocket, length, sizeof (length), 0); if (ret = = SOcket_error) {return false; 
  else if (strcmp (length, "NAK") = = 0) {return false; 
  int size = atoi (length); 
 
  Std::ofstream out; 
  Out.open (name, std::ios::binary); 
    if (!out) {printf ("Cannot save the file\n"); 
  return false; 
    while (size>0) {ret = recv (clientsocket, buffer, buffer_size, 0); int s = size < buffer_size? 
    Size:buffer_size; 
      if (ret = = socket_error) {out.close (); 
    return false; 
      else if (strcmp (buffer, "NAK") = = 0) {out.close (); 
    return false; 
    else {out.write (buffer, s); 
  size = Buffer_size; 
  } out.close (); 
return acknowledge (); 
  BOOL FtpClient::p utfile () {std::ifstream in; 
  Open File In.open (name, std::ios::binary); 
    if (!in) {printf ("Cannot open the file\n"); 
  return false; 
  memset (buffer, 0, sizeof (buffer)); 
  Gets the number of bytes in the file in.seekg (0, Std::ios_base::end); 
  int sp = IN.TELLG (); int total_size = 0; 
  int R; 
  Char length[20]; 
 
  sprintf (length, "%d", SP); 
  Send bytes R = Send (clientsocket, length, sizeof (length), 0); 
  if (r = = Socket_error) {return false; 
    while (sp > 0) {in.clear (); 
    IN.SEEKG (Total_size, Std::ios_base::beg); 
    memset (buffer, 0, sizeof (buffer)); 
    Read file In.read (buffer, sizeof (buffer)); int size = SP < buffer_size? 
    Sp:buffer_size; 
    Total_size + = size; 
 
    Send file R = Send (clientsocket, buffer, size, 0); 
    SP-= size; 
      if (r = = socket_error) {in.close (); 
    return false; 
} in.close (); 
  BOOL Ftpclient::getworkdir () {printf ("getworkdir\n"); 
  memset (buffer, 0, sizeof (buffer)); 
  int ret; 
  Char length[20]; 
  ret = recv (clientsocket, length, sizeof (length), 0); 
  if (ret = = Socket_error) {return false; 
  int size = atoi (length); 
    while (size>0) {ret = recv (clientsocket, buffer, buffer_size, 0); if (ret = = Socket_erroR) {return false; 
    else {printf ('%s ', buffer); 
  size = Buffer_size; 
return true; 
  BOOL Ftpclient::acknowledge () {int ret = recv (clientsocket, buffer, buffer_size, 0); 
    if (Ret > 0) {if (strcmp (buffer, "NAK") = = 0) return false; 
  else if (strcmp (buffer, "ACK") = = 0) return true; 
    } ftpclient::~ftpclient () {if (isconnect) {isconnect = false; 
    Char c[6]; 
    strcpy (C, "close"); 
    Send (Clientsocket, C, strlen (c) + 1, 0); 
  Closesocket (Clientsocket); 
 } 
}

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 = Ten 
  }; 
  Char buffer[buffer_size]; 
  Sockaddr_in Serverchannel; 
  Char name[50]; 
  Char workdir[100]; Store like C:\Users MARK: No slash at the end of the string!! 
  int serversocket;//socket 
  int clientsocket; 
  BOOL SendFile (); 
  BOOL Receivefile (); 
  BOOL Dopwd (); 
  BOOL Docd (); 
  BOOL Isvalidpath (char* path); 
Public: 
  ftpserver (); 
  bool Start ();//open Server 
}; 

FtpServer.cpp

#define _crt_secure_no_warnings #include "ftpServer.h" #include <cstdio> #include <cstdlib> #include <fs 
  tream> #include <cstring> ftpserver::ftpserver () {WORD wversionrequested; 
  Wsadata Wsadata; 
 
  int ret; Winsock Initialization: wversionrequested = Makeword (2, 2);//The version of the Winsock DLL that you want to use RET = WSAStartup (wversionrequested, &wsad 
  ATA); 
  if (ret!= 0) {printf ("WSAStartup () failed!\n"); }//Confirm Winsock DLL support version 2.2:if (Lobyte (wsadata.wversion)!= 2 | | 
    Hibyte (wsadata.wversion)!= 2) {wsacleanup (); 
  printf ("Invalid Winsock version!\n"); 
  //workdir initialized to the current path system ("CD > Tempfile"); 
  Std::ifstream in ("Tempfile", std::ifstream::in); 
  In >> Workdir; 
In.close (); 
 
  BOOL Ftpserver::start () {int on = 1; 
  Initialize Server memset (&serverchannel, 0, sizeof (serverchannel)); 
  serverchannel.sin_family = af_inet; 
  SERVERCHANNEL.SIN_ADDR.S_ADDR = htonl (Inaddr_any); Serverchannel.sin_port = HtoNS (SERVER_PORT); 
  Create Socket This->serversocket = socket (af_inet, sock_stream, ipproto_tcp); 
    if (ServerSocket < 0) {printf ("Cannot create socket\n"); 
  return false; 
  else printf ("successfully create socket\n"); 
 
  SetSockOpt (ServerSocket, Sol_socket, SO_REUSEADDR, (char*) &on, sizeof (on)); 
  bind int b = bind (ServerSocket, (sockaddr*) &serverchannel, sizeof (Serverchannel)); 
    if (b < 0) {printf ("bind error\n"); 
  return false; 
  else printf ("Successfully bind\n"); 
  Listen for int L = Listen (ServerSocket, queue_size); 
    if (L < 0) {printf ("Listen failed\n"); 
  return false; 
  else printf ("Successfully listen\n"); 
  int len = sizeof (Serverchannel); 
    Server waits for connection while (1) {printf (' Waiting for connection...\n '); 
    Accept a connection Clientsocket = Accept (ServerSocket, (sockaddr*) &serverchannel, &len); 
    if (Clientsocket < 0) {printf ("Accept failed\n"); } ELSE {printf ("successfully connect\n"); 
        while (1) {memset (buffer, 0, sizeof (buffer)); 
 
        int ret; 
 
        ret = recv (clientsocket, buffer, buffer_size, 0); 
        if (ret = = socket_error) {printf ("Receive failed\n"); 
          else {char opt[50]; 
          printf ("Successfully receive\n"); 
          int i = 0, j = 0; 
          printf ("buffer =%s\n", buffer); 
            while (Buffer[i]!= ' &&buffer[i]!= ' The "() {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 error\n"); 
}}} 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 file\n"); 
  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 failed\n"); 
  return false; 
  else {printf ("Send success\n"); 
    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 failed\n"); 
    return false; 
    else {printf ("Send success\n"); 
  } 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 failed\n"); 
  return false; 
  else {printf ("successfully receive\n"); 
  int size = atoi (length); 
 
  Std::ofstream out; 
  Out.open (path, std::ios::binary); 
    if (!out) {printf ("Cannot save the file\n"); 
  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 failed\n"); 
    Break 
      else {printf ("successfully receive\n"); 
    Out.write (buffer, s); 
  size = Buffer_size; 
  } out.close (); 
return true; 
  BOOL Ftpserver::d opwd () {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 file\n"); 
  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 failed\n"); 
  return false; 
  else {printf ("Send success\n"); 
    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 =%d\n", total_size); 
 
    R = Send (clientsocket, buffer, size, 0); 
    SP-= size; 
      if (r = = socket_error) {printf ("Send failed\n"); 
    return false; else {printf ("Send success\n"); 
  } 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::d OCD () {for (int i = 0; Name[i]!= ' ", ++i) {if (name[i] = = '/') name[i] = ' \ \ '; if (name[0] = = '. ' &AMP;&AMP;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; 

 }

Main.cpp

#include "ftpServer.h" 
#pragma (lib, "Ws2_32.lib") 
int main () 
{ 
 ftpserver F; 
 F.start (); 

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.