2011-11-12 54 views
1

我學習了C++,現在我想繼續學習一些網絡編程。我決定使用boost :: asio,因爲它是多平臺的。我寫了這個簡單的程序:boost :: asio爲每個客戶端分開的陣列

客戶端:

#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; 
} 

服務器:

#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; 

std::string user_array[100]; 

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; 
    } 


void session(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"; 
     user_array[*ID] = *request_value; 
    } 

     else if (output == 2) 
     { 
     // GET 
     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"; 
    } 
} 

void server(boost::asio::io_service& io_service, short port) 
{ 
    tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port)); 
    for (;;) 
    { 
    socket_ptr sock(new tcp::socket(io_service)); 
    a.accept(*sock); 
    boost::thread t(boost::bind(session, 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; 
} 

基本上,它是允許用戶將數據存儲在服務器上的應用程序。用戶可以使用PUT命令插入新數據,然後輸入ID號和數據值,然後使用GET命令,然後使用ID檢索數據。用戶請求在analyze_user_request函數中處理,隨後寫入或讀取數組。問題是,現在所有的客戶都在使用相同的全球架構。這意味着,如果一個客戶端將某些東西保存在特定ID下,所有其他客戶端都可以讀取它,因爲它們訪問相同的數組我想知道,如何將數組與不同的客戶端關聯起來,並在新客戶端連接時創建一個新數組?

+2

如何在一個類中封裝客戶端? – netcoder

回答

0

如何將會話數據封裝到類中併爲每個連接創建單獨的會話對象。大約它可以是這樣的:

會話類定義:

class Session { 
public: 
// logic from your session function 
void handleRequests(socket_ptr sock); 

private: 
// session data here 
} 

typedef boost::shared_ptr<Session> SessionPtr; 

在「服務器」功能,在接受循環創建新的對象,並把它傳遞給新的線程:

SessionPtr newSession(new Session()); 

boost::thread acceptThread(boost::bind(&Session::handleRequests, newSession, sock)); 

對不起,我可能代碼中的錯誤,我遠離我的開發環境,它無法測試它。

對於處理多個連接separatly看到促進更好的解決方案:: ASIO例如「聊天服務器」:http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/chat/chat_server.cpp

+0

謝謝,我遵循了你的建議,但現在看來每次用戶輸入任何請求時都會創建一個Session類的新實例,因此會創建一個新數組。我目前的代碼在這裏:[鏈接](http://pastebin.com/m4GqMDqa) – user1042840

+0

對不起,延遲迴答。請告訴我客戶端代碼。 – vladv

相關問題