나는 C++을 배웠다. 이제 나는 나아가서 몇 가지 네트워크 프로그래밍을 배우고 싶다. 나는 multiplatform이기 때문에 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;
}
기본적으로, 사용자가 서버에 데이터를 저장 할 수있는 응용 프로그램입니다. ID 번호와 데이터 값이 뒤 따르는 PUT 명령을 사용하여 새 데이터를 삽입하고 GET 명령과 ID를 사용하여 데이터를 검색 할 수 있습니다. 사용자 요청은 analyze_user_request 함수에서 처리 된 후 어레이에 쓰거나 어레이에서 읽습니다. 문제는 이제 모든 클라이언트가 동일한 전역 arry를 사용하고 있다는 것입니다. 즉, 한 클라이언트가 특정 ID 아래에 무언가를 저장하면 다른 클라이언트는 모두 동일한 배열에 액세스하므로 읽을 수 있습니다. 배열을 다른 클라이언트와 어떻게 연관시킬 수 있을까요? 그리고 새로운 클라이언트가 연결될 때 새로운 배열을 생성 할 수 있습니까?
어떻게 클래스의 클라이언트를 캡슐화 어떻습니까? – netcoder