Sockets workflow in FTP imitation

332 Views Asked by At

I am trying to implement client-server communication via sockets. The main tasks are:

  1. Sending commands from clients to server

  2. Sending data from server to clients

  3. Sending data from clients to server

Commands should come via port1, data via port2.

I got it working without without multi-threading but I have some problems with understanding how do I need to handle sockets.

Current scenario:

1.Server starts (socket, bind, listen for both command and info sockets) and goes for infinite loop with this function:

void FTPServer::waitForConnection()
{
  sockaddr_in client;
  int clientsize = sizeof(client);

  SOCKET clientSocket = accept(_infoSocket, (struct sockaddr*)&client, &clientsize);

  if (clientSocket == INVALID_SOCKET)
  {
    cout << " Accept Info Error" << endl;
  }
  else
  {
    cout << " Accept Info OK" << endl;

    char* buff = new char[CHUNK_SIZE];
    string fullRequest;
    int rc = recv(clientSocket, buff, CHUNK_SIZE, 0);
    if (rc == SOCKET_ERROR)
    {
      cout << " Recieve Info Error" << endl;
    }
    else
    {
      buff[rc] = NULL;
      fullRequest.append(buff);
      cout << " Recieve Info OK" <<endl;
      if (executeCommand(fullRequest, clientSocket))
      {
        logOperation(client, fullRequest.c_str());
      }
    }

    delete buff;
  }
}

2.Client starts (socket, connect), creates 2 sockets on same ports, waits for user input.

3.User types "LIST", clients checks that it's a valid command and sends it.

bool FTPClient::sendToServer(string data, const bool verbose)
{
  int n = 0;

  while (data.size() > CHUNK_SIZE)
  {
    string s = data.substr(CHUNK_SIZE).c_str();
    n += send(_infoSocket, data.substr(CHUNK_SIZE).c_str(), CHUNK_SIZE, 0);
    data = data.substr(CHUNK_SIZE+1);
  }
  n+=send(_infoSocket, data.c_str(), data.size(), 0);
  cout<<n<<endl;
  if(n<0)
  {
    cout<<"Error: sending"<<endl;
    return 0;
  }

  if (verbose)
  cout<<"Send "<<n<<" bytes"<<endl;

  return true;
}

4.Servers receives it, accepts on _dataSocket and sends the list of available files.

5.Client receives the list:

string FTPClient::getDataFromServer(const bool verbose)
{
  char data[CHUNK_SIZE];
  int size = recv(_dataSocket, data, strlen(data), 0);
  if (size > 0)
  {
    int n = 0;
    string res;
    while (size > CHUNK_SIZE)
    {
      int buff = recv(_dataSocket, data, CHUNK_SIZE, 0);
      res.append(data);
      size -= buff;
      n += buff;
    }

    n+= recv(_dataSocket, data, CHUNK_SIZE, 0);
    res.append(data);
    if (verbose)
    cout<<"Recevied "<<n<<" bytes"<<endl;

    res.resize(n);
    return res;
  }
  else
  {
    return "";
  }
}

Till this, it works. But if try to execute same command again, I got nothing. I think, problem is that for each connect we need an accept on server side. In main loop server gets only one connect from client. Is closing client command socket and reconnecting it on every request only option here? Any other advices (except for "Google it") are highly appreciated.

0

There are 0 best solutions below