رفتن به مطلب
مرجع رسمی سی‌پلاس‌پلاس ایران

Max Base

اساتید
  • تعداد ارسال ها

    8
  • تاریخ عضویت

  • روز های برد

    4

نوشته‌های وبلاگ ارسال شده توسط Max Base

  1. Max Base
    سلام.
    عدم دسترسی به یک سیستم مناسب و با خبر نبودن از حساب کاربری گیت هاب خود یکی از مشکلاتی بود که در این چند ساله برنامه نویسان با آن روبرو بودند.
    چک کردن حساب ایمیل در تلفن همراه می توانست تا حدودی به این موضوع کمک کند. اما یک اپلیکیشن اختصاصی برای این مورد می تواند این امر را به بهترین شکل پوشش دهد.
    بعد از کارهایی که برروی اپلیکیشن رسمی شرکت گیت هاب برای پلتفرم iOS انجام شد و خوشبختانه بدون هیچ مشکلی در بزرگ رویداد و کنفرانس شرکت و مایکروسافت - GitHub Universe 2019 در تاریخ November 13-14, 2019 رونمایی شد. به عنوان یکی از اعضای شرکت این نوید را می دهم که نوبت به آن رسید تا اپلیکیشن برای اندروید نیز پیاده شود.
    در حال حاضر این اپلیکیشن در حال توسعه است و هنوز رونمایی نشده است.
    برای این اپلیکیشن میزان پشتیبانی API 21+ Android device در نظر گرفته شده است و خواهد توانست از نسخه Android 5.0 به بالا را پشتیبانی کند.
    می توانید پیشنهادات و نظرات خود را نیز ایمیل کنید. Max [@] Asrez {.DOR.} com
    Hi, I'm Max Base.
    GitHub team did work on the official GitHub application for the iOS platform and fortunately unveiled at the big event and conference(GitHub Universe 2019 on November 13-14, 2019). As a member of the company, I have the promise that the app will launch for Android.
    This app is currently under development and has not been unveiled yet.
    This app is designed to support Android 21+ API and will support Android 5.0 or later.
    You can also email your suggestions and comments. Max [@] Asrez {.DOR.} com
    Best,
    Max Base

     


     




    با تشکر
    Max Base / مکس بیس
  2. Max Base
    با سلام وقت بخیر,
    در این مطلب میخواهیم در مورد روش کارکرد پیام رسان ها بیشتر بدانیم و با یکدیگر کد یک پیام رسان ساده را پیاده و بررسی کنیم. 

    طرز کار کرد پیام رسان
    در نظر داشته باشید که هر پیام رسانی که بر ساختار ها پیاده شده باشد از دو قسمت تشکیل شده است.
    نرم افزار اصلی برای مدیریت درخواست ها (سرور) نرم افزار برای کاربران (کاربر) به نرم افزار اولی سمت SERVER خواهیم گفت و به بعدی سمت CLIENT خواهیم گفت.
    روم یا تالار گفتگو
    ما تنها یک اتاق برای گفتگو در نظر میگیریم و هر کاربری که به سرور متصل شود را در همان تالار اضافه خواهیم کرد.
    تالار های گفتگو صرفا برای تقکیک سازی ارسال و دریافت ها و محدود کردن بازه ی کاربران مورد نظر... (ممکن است یک کاربر در چند اتاق بطور همزمان باشد.)
    سیستم های پیام رسان پیشرفته تر مانند تلگرام و ... تالار های زیادی را شامل می شوند. (هر کاربر خودش در کانال و گروه های مختلفی عضو است که هر کدام از آنها یک کانال متفاوت محسوب می شوند.)
    * دقت شود که منظور از کانال صرفا یک اتاق یا تالار گفتگو است و منظور کانال ارتباطی و پروتکل نیست.
    نرم افزار اصلی
    نرم افزار اصلی وظیفه دارد تا تمام کاربرانی که وارد تالار شده اند را به یاد داشته باشد و هر لحظه اماده دریافت درخواست هایی از طرف کاربرانش باشد. و پیام هایی را که از کاربران دریافت می کند برای تمامی کاربران دیگر هم ارسال کند که بسته به خلاقیت و نیاز می تواند هر یک از این بخش ها متفاوت طراحی شود.
    نرم افزار اصلی باید از قبل اجرا شده باشد. تا کاربران دیگر با استفاده از نرم افزار مخصوص به خودشان بتوانند به سرور متصل شوند و ارسال و دریافت داشته باشند.
    در نظر داشته باشید که اگر در نرم افزار اصلی اختلالی پیش بیایید و متوقف بشوند. قطا برای تمام کاربران مشکل پیش می آید. مگر اینکه از پایگاه های داده ی داخلی استفاده کرده باشند. (با خلاقیت می توان به گونه های متفاوتی چنین ساختاری را پیاده کرد)
    نرم افزار کاربران
    این نرم افزار جذاب ترین بخش است چرا تمام قابلیت هایی را که در اختیار کاربر قرار می دهیم را مستقیما طراحی می کنیم.
    در نظر داشته باشید که هر چیزی که در این نرم افزار طراحی می شود باید در نرم افزار اصلی پشتیبانی شوند... بنابراین اگر این دو بخش توسط دو فرد یا دو گروه مجزا طراحی می شوند آنها باید توسط داکیومنت ها و جلساتی به نظرات مشابه ای رسیده باشند. (اگرچه اینها تخصص و وظیفه ی تحلیلگر سیستم است! نه بطور همزمان وظیفه توسعه دهنده و برنامه نویس نرم افزار)
    پیاده سازی یک نمونه
    اکنون در نظر داریم تا با استفاده از ساختار کتابخانه BoostAsio پروژه ای را با نام BoostAsioChat ایجاد کنیم که در آن می خواهیم یک پیام رسان با حداقل ترین امکانات پایه طراحی کنیم که بیشتر جنبه شخصی و تفریحی دارد. زیرا از ساختار های استاندارد و ایمن و کاربری کاملا بدور است! (می توانید خودتان توسعه دهید و آنرا جالب تر بسازید)
     
    ساختار نرم افزار اصلی و سرور را به این صورت تعریف می کنیم :
    typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant); void deliver(const message& messageItem); void leave(participantPointer participant); private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room); void start(); void deliver(const message& messageItem); private: void readHeader(); void readBody(); void write(); tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint); private: void do_accept(); tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]); ساختار نرم افزار کاربر را هم به این صورت تعریف می کنیم :
    typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context); void write(const message& messageItem); void close(); private: void connect(const tcp::resolver::results_type& endpoints); void readHeader(); void readBody(); void write(); boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]);  
    در نظر داریم تا در این پروژه از thread ها نیز استفاده کنیم... در مورد این مفهوم ها می توانید بصورت مجزا تحقیق کنید.
    بنابراین روش کامپایل این پروژه به این صورت خواهد بود :
     
    $ g++ client.cpp -lpthread -o client $ g++ Server.cpp -lpthread -o server  
    آزمایش
    همانطور که گفته شد در ابتدا نرم افزار اصلی و سرور باید اجرا شود.
    در اینجا ما تمام ارتباطات شبکه را بر روی یک سیستم در شبکه داخلی برقرار خواهیم کرد... پس نگرانی در مورد ساختار های درونی شبکه و آی پی / دی ان اس / دامین نخواهیم داشت.
    بنابراین ای پی را می توانید ای پی داخلی یا  localhost  در نظر بگیرید.
    برای آزمایش پورت فرضی 4000 را در نظر میگیریم و نرم افزار اصلی را روی این پورت اجرا میکنیم :
     
    $ ./server 4000 در این مرحله متوجه می شوید که نرم افزار اصلی با موفقیت اجرا شده است و همچنان اجرا مانده است. بله درست است... نرم افزار اصلی هر لحظه باید منتظر دستور کاربران باشد.
    اگر لحظه ای برای نرم افزار اصلی اختلالی پیش آید نخواهد توانست دستورات کاربران را انجام یا پاسخ دهد.
    بنابراین این پردازش را قطع نکنید و اجازه دهید تا نرم افزار اصلی اجرا بماند. در محیط دیگری نرم افزار سمت کاربر را نیز اجرا کنید.
    این نرم افزار را می توانید به تعداد دلخواه وارد کنید. (همانطور که ممکن است 6 نفر همزمان به سرور متصل باشند / یا ممکن است هیچ فردی به سرور متصل نشوند)
     
    ابتدا یک کاربری را به سرور با پورت 4000 و شبکه داخلی وصل می کنیم :
     
    $ ./client localhost 4000 first user: you can type message here... حال در محیط دیگری با کاربر جدیدی نیز وارد می شویم :
    $ ./client localhost 4000 second user: you can type message here... در این پروژه نمونه از کاربران نام کاربری یا نام نمی پرسیم.. و صرفا وقتی وارد محیط گفتگو می شوند... یا زمانی که به سرور متصل می شوند منتظر هستیم تا انها پیامی را بنویسند...
    هر پیامی را که بنویسند به سرور ارسال می شود و سرور وظیفه دارد تا آنرا برای تمام کاربران بفرستد. و این روند درون یک حلقه بی نهایت تکرار می شوند.
    پس این ارتباط دو طرفه خواهد بود و هم کاربران برای سرور اطلاعات ارسال می کنند و هم سرور برای کاربران اطلاعات ارسال خواهد کرد.
    در نظر داشته باشید که کاربر اول می تواند پیامی را بنویسد و به کاربران دیگر ارسال شود. ممکن است کاربر سومی اصلا تصمیمی به نوشتن پیام نداشته باشد و صرفا تمایل به خواندن پیام دیگران داشته باشند. و این کاملا اختیاری است. و ما کاربران را اجباری نمیکنیم. اگرچه شما می توانید با خلاقیت خودتان اینها را با متغییر های کمکی و دستورات شرطی پیاده کنید.
    کد ها
    برای پیام ها یک ساختار در نظر میگیریم و بصورت مشترک در هر دو نرم افزار استفاده خواهیم کرد... بنابراین اینرا در هدر پیاده خواهیم کرد.
    هدر پیام : (message.hpp)
    #ifndef message_HPP #define message_HPP #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; class message { public: enum { headerLength = 4 }; enum { maxBodyLength = 512 }; message() : bodyLength_(0) { } const char* data() const { return data_; } char* data() { return data_; } size_t length() const { return headerLength + bodyLength_; } const char* body() const { return data_ + headerLength; } char* body() { return data_ + headerLength; } size_t bodyLength() const { return bodyLength_; } void bodyLength(size_t new_length) { bodyLength_ = new_length; if(bodyLength_ > maxBodyLength) bodyLength_ = maxBodyLength; } bool decodeHeader() { char header[headerLength + 1] = ""; strncat(header, data_, headerLength); bodyLength_ = atoi(header); if(bodyLength_ > maxBodyLength) { bodyLength_ = 0; return false; } return true; } void encodeHeader() { char header[headerLength + 1] = ""; sprintf(header, "%4d", static_cast<int>(bodyLength_)); memcpy(data_, header, headerLength); } private: char data_[headerLength + maxBodyLength]; size_t bodyLength_; }; #endif نرم افزار اصلی و سرور : (server.cpp)
    #include <iostream> #include <cstdlib> #include <deque> #include <memory> #include <list> #include <set> #include <utility> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant) { participants.insert(participant); for(auto messageItem: messageRecents) participant->deliver(messageItem); } void deliver(const message& messageItem) { messageRecents.push_back(messageItem); while(messageRecents.size() > max) messageRecents.pop_front(); for(auto participant: participants) participant->deliver(messageItem); } void leave(participantPointer participant) { participants.erase(participant); } private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room) { } void start() { room_.join(shared_from_this()); readHeader(); } void deliver(const message& messageItem) { bool write_in_progress = !Messages.empty(); Messages.push_back(messageItem); if(!write_in_progress) { write(); } } private: void readHeader() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.data(), message::headerLength), [this, self](boost::system::error_code ec, size_t) { if(!ec && messageItem.decodeHeader()) { readBody(); } else { room_.leave(shared_from_this()); } }); } void readBody() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.body(), messageItem.bodyLength()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { room_.deliver(messageItem); readHeader(); } else { room_.leave(shared_from_this()); } }); } void write() { auto self(shared_from_this()); boost::asio::async_write(socket, boost::asio::buffer(Messages.front().data(), Messages.front().length()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { Messages.pop_front(); if(!Messages.empty()) { write(); } } else { room_.leave(shared_from_this()); } }); } tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint) { do_accept(); } private: void do_accept() { acceptor.async_accept([this](boost::system::error_code ec, tcp::socket socket) { if(!ec) { make_shared<session>(move(socket), room_)->start(); } do_accept(); }); } tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]) { try { if(argc < 2) { cerr << "Usage: server <port> [<port> ...]\n"; return 1; } boost::asio::io_context io_context; list<server> servers; for(int i = 1; i < argc; ++i) { tcp::endpoint endpoint(tcp::v4(), atoi(argv[i])); servers.emplace_back(io_context, endpoint); } io_context.run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } نرم افزار دوم و سمت کاربر : (client.cpp)
    #include <iostream> #include <thread> #include <cstdlib> #include <deque> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context) { connect(endpoints); } void write(const message& messageItem) { boost::asio::post(context, [this, messageItem]() { bool write_in_progress = !writeMessage.empty(); writeMessage.push_back(messageItem); if(!write_in_progress) { write(); } }); } void close() { boost::asio::post(context, [this]() { socket.close(); }); } private: void connect(const tcp::resolver::results_type& endpoints) { boost::asio::async_connect(socket, endpoints, [this](boost::system::error_code ec, tcp::endpoint) { if(!ec) { readHeader(); } }); } void readHeader() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.data(), message::headerLength), [this](boost::system::error_code ec, size_t) { if(!ec && readMessage.decodeHeader()) { readBody(); } else { socket.close(); } }); } void readBody() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.body(), readMessage.bodyLength()), [this](boost::system::error_code ec, size_t) { if(!ec) { cout.write(readMessage.body(), readMessage.bodyLength()); cout << "\n"; readHeader(); } else { socket.close(); } }); } void write() { boost::asio::async_write(socket, boost::asio::buffer(writeMessage.front().data(), writeMessage.front().length()), [this](boost::system::error_code ec, size_t) { if(!ec) { writeMessage.pop_front(); if(!writeMessage.empty()) { write(); } } else { socket.close(); } }); } boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]) { try { if(argc != 3) { cerr << "Usage: client <host> <port>\n"; return 1; } boost::asio::io_context context; tcp::resolver resolver(context); auto endpoints = resolver.resolve(argv[1], argv[2]); client c(context, endpoints); thread t([&context](){ context.run(); }); char line[message::maxBodyLength + 1]; while(cin.getline(line, message::maxBodyLength + 1)) { message messageItem; messageItem.bodyLength(strlen(line)); memcpy(messageItem.body(), line, messageItem.bodyLength()); messageItem.encodeHeader(); c.write(messageItem); } c.close(); t.join(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; }  
     این پروژه آزمایشی بصورت رایگان و اوپن سورس در اینترنت بخصوص اینجا وجود دارد و می توانید آنرا مستقیما بصورت کامل دانلود کنید.   
    با تشکر,
    Max Base / مکس بیس
  3. Max Base
    سلام وقت بخیر,
    گیت هاب پیج
    گیتهاب پیج یک سرویس میزبانی وب است که توسط Github اراعه شده است که با استفاده از آن می توانید حتی صفحاتی Static را در پلتفرم وب میزبانی کنید و حتی ابزار هایی مانند Jekyll را می توانید روی این بستر (Github Pages) پیاده و اجرا کنید که در قسمت های آینده در مورد آن توضیح خواهم داد.
    میزبانی وب سایت هایی که بر پایه Github Pages هستند بصورت رایگان هست و دیگر نیازی به دامین, هاست و سرور وجود ندارد.
    حساب های گیت هاب
    تمام حساب هایی که در سایت گیت هاب وجود دارند دو نوع هستند.
    حساب کاربری و شخصی حساب سازمانی (تیم) بطور مثال :
    حساب هایی مانند:
    Kambiz-Asadzadeh (Kambiz Asadzadeh), BaseMax (Max Base), ccoreghaesm (Ghasem Ramezani), HamedMasafi (Hamed Masafi)  همگی حساب های فرد و شخصی هستند.
    و حساب هایی مانند :
    Microsoft · GitHub,  Google · GitHub,  TeamSnap · GitHub,  iOSTREAM · GitHub  .حساب هایی سازمانی (تیم) هستند
    هر حساب کاربری و شخصی این قابلیت را دارد تا بتواند یک حساب سازمانی ایجاد کند.
    ایجاد حساب سازمانی (تیم)
    برای ایجاد کردن یک حساب سازمانی, بعد از عضویت و ایجاد یک حساب کاربری در Github و وارد شدن به حساب کاربریتان, به اینجا مراجعه کنید تا یک سازمان جدیدی ایجاد کنید.

     
    گیت هاب پیج
    به موضوع اصلی برمیگردیم. تا کنون در مورد انواع حساب ها توضیح داده ایم. حال در نظر داشته باشید که هر حساب کاربری (عادی یا سازمانی) این قابلیت را دارد تا بتواند یک میزبانی برای خودش رزرو کند.
    در حالت پیشفرض میزبانی ها بصورت رایگان بر روی دامین GitHub Pages قرار دارند، با اینحال بطور مثال اگر شما یک حساب (شخصی یا سازمانی) بنام test456 دارید می‌توانید میزبانی خود را بر روی دامین http://test456.github.io فعال کنید.
    آزمایشگاه و انجام بصورت عملی
    در حال حاظر من خودم یک سازمان (تیم) بنام MaxFork با آدرس Max Fork · GitHub در اختیار دارم.
    می خواهم یک میزبانی وب جدید روی این حساب ایجاد کنم.

    گزینه New را لمس کنید و یک مخزن جدید (پروژه) ایجاد کنید.
    دقت کنید که نام پروژه اهمیت دارد را آدرس میزبانی که مد نظرمان هست وارد می کنیم.
    بطور مثال : MaxFork.Github.io
    محتوای Description اختیاری است و می توانید هر چه میخواهید وارد کنید. چون بعدا هم امکان ویرایش کردن آن برایتان وجود ندارد.
    نوع پروژه را می توانید Public یا Private تنظیم کنید. با توجه به اینکه حساب های اکثر افراد معمولی هست گمان میکنم امکان تنظیم کردن از نوع Private برای آنها همراه با میزبانی وب وجود نداشته باشد. بنابراین Public را انتخاب کنید. 
    پیاده کردن یک فایل README برای مخزن اختیاری است و می توانید آنرا ایجاد کنید.
    همچنین تصمیم شما در مورد انتخاب لایسنس نیز آزادانه است و می توانید خودتان شخصا در مورد آن فکر و تصمیم بگیرید.

    برای امتحان می توانید فایلی بنام index.html را با یک محتوای آزمایشی ایجاد کنید.
    در حال حاظر وب سایتی با آدرس https://maxfork.github.io در دسترس وجود دارد و محتوایی را که در فایل نوشته ایم را نشان می دهد.
     
    در انتهای بخش Settings در قسمت GitHub Pages می توانید وضعیت میزبانی را بررسی کنید.
    در قسمت ذکر شده می توانید قالب های از قبل تعریف شده را مشاهده و انتخاب کنید.
    همچنین امکان تنظیم Custom domain برای میزبانی را هم دارید.
     
    همچنین می توانید فایل های دیگری نیز مانند test.html همراه با پوشه و مسیردهی ایجاد کنید.
    بطور مثال اکنون ما فایل new.html را در شاخه اصلی مخزن ایجاد کردیم که در آدرس زیر قابل دسترس است:
    https://maxfork.github.io/new.html
    فایلی بنام _config.yml از قبل تعریف شده است که می توانید بصورت دستی هم ایجاد کنید که در آن نام قالب / تنظیمات / پلاگین و ماژول هایی را که نیاز دارید می توانید تعریف کنید.
    در قسمت های بعدی در مورد Static بیشتر توضیح خواهم داد، پیشنهاد می‌کنم در مورد Textile و Markdown هم مطالعه کنید.
     
    سپاس
    Max Base / مکس بیس
×
×
  • جدید...