mif هو إطار تطبيق ويب C++ 11 مصمم لتطوير الخدمات الصغيرة الخلفية. يستخدم الإطار المعلومات الوصفية الإضافية.
1.5.1
ملاحظة: تم تطوير الفرع الرئيسي بشكل نشط، استخدم الإصدار الأحدث لاستخدام الإنتاج.
تم اختباره أخيرًا على إصدار دول مجلس التعاون الخليجي 13.2
Linux (تم اختباره أخيرًا على Ubuntu 23.10)
git clone https://github.com/tdv/mif.git
cd mif
./download_third_party.sh
mkdir build
cd build
cmake ..
make
make install
ملاحظة: في Ubuntu، قد يتعين عليك تثبيت بعض الحزم الإضافية: liblz4-dev، pkgconf، bison، flex
يمكنك محاولة استخدام CMAKE_INSTALL_PREFIX لتحديد دليل التثبيت
بعد إنشاء mif ، يمكنك إنشاء أمثلة
cd mif /examples/{sample_project}
mkdir build
cd build
cmake ..
make
ملاحظة: لتطوير تطبيقاتك، يمكنك استخدام قالب التطبيق. بعد تنزيل مشروع mif اتبع الخطوات
cd mif /template
mkdir build
cd build
cmake ..
make
بعد ذلك يمكنك تغيير هذا القالب لإنشاء التطبيق الخاص بك. بالإضافة إلى ذلك، يمكنك استخدام الأمثلة المنجزة من القالب. الأمثلة مكتملة بالكامل وتحتوي على برنامج نصي للبناء نفسه. كلهم موجودون في مجلد _docs. يمكنك العثور على وثائق مفصلة للأمثلة في الويكي.
الخادم:
cd mif /exammples/{sample_project}/bin
./{sample_project}_server
عميل:
cd mif /exammples/{sample_project}/bin
./{sample_project}_client
الرجاء استخدام --help للحصول على مزيد من المعلومات حول تشغيل مثال
كود المصدر
وصف
يوضح المثال عمل خادم صدى HTTP البسيط. خادم صدى HTTP
// mif
# include < mif /application/http_server.h >
# include < mif /common/log.h >
# include < mif /net/http/constants.h >
class Application
: public mif ::Application::HttpServer
{
public:
using HttpServer::HttpServer;
private:
// mif .Application.HttpServer
virtual void Init ( mif ::Net::Http::ServerHandlers &handlers) override final
{
handlers[ " / " ] = [] ( mif ::Net::Http::IInputPack const &request,
mif ::Net::Http::IOutputPack &response)
{
auto data = request. GetData ();
mif _LOG (Info) << " Process request " " << request. GetPath () << request. GetQuery () << " "t Data: "
<< (data. empty () ? std::string{ " null " } : std::string{ std::begin (data), std::end (data)});
response. SetCode ( mif ::Net::Http::Code::Ok);
response. SetHeader ( mif ::Net::Http::Constants::Header::Connection::Value,
mif ::Net::Http::Constants::Value::Connection::Close::Value);
response. SetData ( std::move (data));
};
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
امتحان
curl -iv -X POST " http://localhost:55555/ " -d ' Test data '
كود المصدر
وصف
يوضح المثال عمل خادم HTTP بواجهة مزدوجة لمعالجة طلبات HTTP الأولية و mif RPC بواسطة HTTP. المزيد يمكنك رؤيته في قسم "خدمة الويب. إضافية"
كود المصدر
وصف
يوضح مثال "Hello World" تطبيقًا أساسيًا لخادم العميل مع تنظيم RPC القائم على الواجهة واتصال TCP باستخدام Boost.archives لتسلسل البيانات
الخطوات الأساسية لإنشاء تطبيق خادم عميل باستخدام RPC
واجهة مشتركة
// STD
# include < string >
// mif
# include < mif /service/iservice.h >
namespace Service
{
struct IHelloWorld
: public mif ::Service::Inherit< mif ::Service::IService>
{
virtual void AddWord (std::string const &word) = 0;
virtual std::string GetText () const = 0;
virtual void Clean () = 0;
};
} // namespace Service
المعلومات الفوقية للواجهة المشتركة
// STD
# include < string >
// mif
# include < mif /remote/ps.h >
// THIS
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Meta
{
using namespace ::Service ;
mif _REMOTE_PS_BEGIN (IHelloWorld)
mif _REMOTE_METHOD (AddWord)
mif _REMOTE_METHOD (GetText)
mif _REMOTE_METHOD (Clean)
mif _REMOTE_PS_END ()
} // namespace Meta
} // namespace Service
mif _REMOTE_REGISTER_PS (Service::Meta::IHelloWorld)
تنفيذ واجهة الخادم
...
// mif
# include < mif /service/creator.h >
// THIS
# include " common/id/service.h "
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Detail
{
namespace
{
class HelloWorld
: public IHelloWorld
{
public:
...
private:
...
// IHelloWorld
virtual void AddWord (std::string const &word) override final
{
...
}
virtual std::string GetText () const override final
{
...
}
virtual void Clean () override final
{
...
}
};
} // namespace
} // namespace Detail
} // namespace Service
mif _SERVICE_CREATOR
(
::Service::Id::HelloWorld,
::Service::Detail::HelloWorld
)
تطبيق الخادم
// mif
# include < mif /application/tcp_service.h >
// COMMON
# include " common/id/service.h "
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpService
{
public:
using TcpService::TcpService;
private:
// mif .Application.TcpService
virtual void Init ( mif ::Service::FactoryPtr factory) override final
{
factory-> AddClass <Service::Id::HelloWorld>();
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
تطبيق العميل
// mif
# include < mif /application/tcp_service_client.h >
# include < mif /common/log.h >
// COMMON
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpServiceClient
{
public:
using TcpServiceClient::TcpServiceClient;
private:
// mif .Application.TcpServiceClient
virtual void Init ( mif ::Service::IFactoryPtr factory) override final
{
auto service = factory-> Create <Service::IHelloWorld>( " HelloWorld " );
mif _LOG (Info) << " Add words. " ;
service-> AddWord ( " Hello " );
service-> AddWord ( " World " );
service-> AddWord ( " !!! " );
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
mif _LOG (Info) << " Clean. " ;
service-> Clean ();
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
كود المصدر
وصف
هذا المثال هو نفس "Hello World". يكمن الاختلاف في استدعاء الأساليب البعيدة باستخدام هياكل البيانات المعرفة من قبل المستخدم كمعلمات وإرجاع القيمة. هيكل المشروع هو نفسه كما في مثال المشروع السابق، نضيف فقط تعريف هياكل البيانات والمعلومات الوصفية المحددة من قبل المستخدم.
هياكل بيانات المستخدم
// STD
# include < cstdint >
# include < map >
# include < string >
namespace Service
{
namespace Data
{
using ID = std::string;
struct Human
{
std::string name;
std::string lastName;
std:: uint32_t age = 0 ;
};
enum class Position
{
Unknown,
Developer,
Manager
};
struct Employee
: public Human
{
Position position = Position::Unknown;
};
using Employees = std::map<ID, Employee>;
} // namespace Data
} // namespace Service
المعلومات الفوقية
// mif
# include < mif /reflection/reflect_type.h >
// THIS
# include " common/data/data.h "
namespace Service
{
namespace Data
{
namespace Meta
{
mif _REFLECT_BEGIN (Human)
mif _REFLECT_FIELD (name)
mif _REFLECT_FIELD (lastName)
mif _REFLECT_FIELD (age)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Position)
mif _REFLECT_FIELD (Unknown)
mif _REFLECT_FIELD (Developer)
mif _REFLECT_FIELD (Manager)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Employee, Human)
mif _REFLECT_FIELD (position)
mif _REFLECT_END ()
} // namespace Meta
} // namespace Data
} // namespace Service
mif _REGISTER_REFLECTED_TYPE (::Service::Data::Meta::Human)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Position)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Employee)
كود المصدر
وصف
بالمقارنة مع الأمثلة السابقة، يضيف هذا المثال وراثة الواجهة. في التنفيذ، يمكنك الاستعلام عن واجهة خارج التسلسل الهرمي.
كود المصدر
وصف
يوضح مثال "الزائر" آلية عمليات الاسترجاعات عن بعد لطرق الواجهة. يمكن استخدام هذا كنقطة بداية للتطبيقات القائمة على النشر/الاشتراك.
كود المصدر
وصف
يوضح المثال Json API (عمليات CRUD) على خادم HTTP.
امتحان
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
كود المصدر
وصف
يوضح المثال الاتصال بين خدمتين صغيرتين (المثال هو إصدار أقوى من http Crud). امتحان
./storage —config=storage.xml
./service --config=service.xml
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
كود المصدر
وصف
يوضح المثال آلية انعكاس بنية بيانات C++. يمكن استخدام هذا كنقطة بداية لإنشاء تطبيق باستخدام التسلسل وORM وREST API.