Boost logo

Boost Users :

Subject: [Boost-users] BEGINNER - separate array for each client
From: wempwer_at_[hidden]
Date: 2011-11-25 14:37:45


I'm learning boost. I'd like to write a simple application that allows user to store data on server. User can insert new data using PUT command followed by ID number and data value, and retrieve data using GET command followed by ID. User requests are processed in analyze_user_request function and are subsequently written to or read from array. The thing is that I want every client to refer to his own array. That means that if one client saves something under particular ID this data is visible only to him. I wonder, how can I associate array with different clients, and create a new array when a new client connects? I tried encapsulating private data in class, but it doesn't seem to work, because now a new array is created every time user enters any request. This is my code:

//CLIENT
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

enum { max_length = 1000000 };

int main(int argc, char* argv[])
{
    while(1)
      {

  try
  {
    if (argc != 3)
    {
      std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
      return 1;
    }

    boost::asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
    tcp::resolver::iterator iterator = resolver.resolve(query);

    tcp::socket s(io_service);
    s.connect(*iterator);

    using namespace std; // For strlen.
        
    std::cout << "Enter message: ";
    char request[max_length];
    std::cin.getline(request, max_length);
    if (request == "\n")
      continue;
    
    size_t request_length = strlen(request);
    boost::asio::write(s, boost::asio::buffer(request, request_length));

    char reply[max_length];
    boost::system::error_code error;
    size_t reply_length = s.read_some(boost::asio::buffer(reply), error);
            
   if (error == boost::asio::error::eof)
     break; // Connection closed cleanly by peer.
   else if (error)
     throw boost::system::system_error(error); // Some other error.

        

    
    std::cout << "Reply is: ";
    std::cout.write(reply, reply_length);
    
    std::cout << "\n";
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
    exit(1);
  }
  }
  
  return 0;
}

//SERVER
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <string>

using boost::asio::ip::tcp;
const int max_length = 1000000;

typedef boost::shared_ptr<tcp::socket> socket_ptr;

unsigned short analyze_user_request(std::string& user_request, short unsigned* ID, std::string* request_value)
{
  // function returns:
  // 0: if user request is incorrect
  // 1: if user requests "PUT" operation
  // 2: if user requests "GET" operation
  // Furthermore, if request is correct, its value (i.e. ID number and/or string) is saved to short unsigned and string values passed by pointers.

 boost::regex exp("^[[:space:]]*(PUT|GET)[[:space:]]+([[:digit:]]{1,2})(?:[[:space:]]+(.*))?$");

  boost::smatch what;
  if (regex_match(user_request, what, exp, boost::match_extra))
   {
     short unsigned id_number = boost::lexical_cast<short unsigned>(what[2]);
     
     if (what[1] == "PUT")
       {
                boost::regex exp1("^[a-zA-Z0-9]+$");
         std::string value = boost::lexical_cast<std::string>(what[3]);
         if (value.length() > 4095)
           return 0;
         if (!regex_match(value, exp1))
           return 0;
         else
           {
              *request_value = value;
              *ID = id_number;
             return 1;
           }
       }
   
     if (what[1] == "GET")
       {
         *ID = id_number;
         return 2;
       }
     
   }
  
  if (!regex_match(user_request, what, exp, boost::match_extra))
    return 0;
   }

class Session
{
public:
  void handleRequest(socket_ptr sock)
{
  try
  {
    for (;;)
    {
      char data[max_length];

      boost::system::error_code error;
      size_t length = sock->read_some(boost::asio::buffer(data), error);
      if (error == boost::asio::error::eof)
        break; // Connection closed cleanly by peer.
      else if (error)
        throw boost::system::system_error(error); // Some other error.
      // convert buffer data to string for further procession
      std::string line(boost::asio::buffers_begin(boost::asio::buffer(data)), boost::asio::buffers_begin(boost::asio::buffer(data)) + length);
      std::string reply; // will be "QK", "INVALID", or "OK <value>"
           unsigned short vID;
      
      unsigned short* ID = &vID;
      std::string vrequest_value;
      std::string* request_value = &vrequest_value;
      
      unsigned short output = analyze_user_request(line, ID, request_value);
      
      if (output == 1)
        {
        // PUT
          reply = "OK";
          std::cout << "PUT operation - ID: " << *ID << " request value: " << *request_value << "\n";
          
          user_array[*ID] = *request_value;
        }
      
              else if (output == 2)
          {
            // GET
          std::cout << "GET operation - ID: " << *ID << " request value: " << *request_value << "\n";
            reply = user_array[*ID];
            if (reply == "")
              reply = "EMPTY";
          }
      
        else
          reply = "INVALID";

            boost::system::error_code ignored_error;
            size_t ans_len=reply.length();
            boost::asio::write(*sock, boost::asio::buffer(reply));
            
    }
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception in thread: " << e.what() << "\n";
  }
}

private:
  std::string user_array[100];
};

typedef boost::shared_ptr<Session> SessionPtr;
  
void server(boost::asio::io_service& io_service, short port)
{
  std::cout << "In \"server\" function\n";
  
  tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
  for (;;)
  {
    socket_ptr sock(new tcp::socket(io_service));
    a.accept(*sock);

    SessionPtr newSession(new Session());
    boost::thread acceptThread(boost::bind(&Session::handleRequest, *newSession, sock));
  }
}

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 2)
    {
      std::cerr << "Usage: blocking_tcp_echo_server <port>\n";
      return 1;
    }

    boost::asio::io_service io_service;

    using namespace std; // For atoi.
    server(io_service, atoi(argv[1]));
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net