رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران

Max Base

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

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

  • روز های برد

    2

آخرین بار برد Max Base در 24 خرداد

Max Base یکی از رکورد داران بیشترین تعداد پسند مطالب است !

اعتبار در سایت

8 خوب

درباره Max Base

کاربـــر رسمی
میانجی گر‌ها
  • تاریخ تولد 6 خرداد 1342

اطلاعات شبکه‌ای

موقعیت

  • شهر
    Remote
  1. Max Base

    با سلام وقت بخیر, این دومین پیام و اولین پاسخی است که در این انجمن ارسال می کنم. این را هم ذکر کنم که سوالتان واضح و شفاف علمی نیست. ذکر کردید که یک تابعی بنام Calculate دارید که ممکن است در شرایط مختلف نیاز به عملکرد متفاوتی رو داشته باشید. خب در این حالت نیاز به یک حافظه برای تعیین وضعیت دارد. بطور مثال اگر وضعیت 0 بود باید عملیات های مشخص شده ای انجام دهد و اگر 1 بود دستورات خاص و مجزای دیگری... برای نگهداری وضعیت کنونی می توانید از یک متغییر یا هر تکنیک دیگری حتی فایل استفاده کنید. که با فراخوانی و خواندن مقدار آن در داخل تابع Calculate می توانید تکلیف خودتان را مشخص کنید تا چه نوع عملیات و دستوراتی را اجرا کنید. نمونه مشابه در C : int state=0; void calculate() { if(state == 0) { // ... } else { // ... } // OR // // switch(state) { // case 0: break; // case 1:break; // } } void changeState() { if(state == 0) { state=1; } else { state=0; } } ممکن است منظورتان را درست و کامل متوجه نشده باشم و راهنمای بی فایده ای در مسیر دیگه ای کرده باشم. هنگامی که به تنها به عنوان این مطلب نگاهی میکنم, بنظرم بهتر است اینگونه بگویم که : شما در زمان اجرا نمی توانید تصمیم جدیدی برای نوشتن دستوراتی جدید برای اجرا بگیرید. (بصورت منطقی) چون کد ها از قبل باید کامپایل شده باشند و موتور کامپایلر در زمان اجرا در کنار شما نخواهد بود. (در حالت کلی) چند سال پیش این قابلیت در تیم توسعه گوگل برای زبان برنامه نویسی گو مطرح شد تا بر روی این قابلیت کار شود تا بتوانیم در زمان اجرا کامپایلی را انجام دهیم, شخصا پیگیر این موضوع بودم. اگرچه تا کنون فقط پشتیبانی محدودی دارد و امید است تا تا سال آینده پشتیبانی این موضوع کامل شود. اگرچه این موضوع چیزی نیست که شما مطرح کردید. چون حتی برای این موضوع یک کامپایلر کوچک برای زمان اجرا کنار برنامه خواهد بود که قطعا حجمی نسبتا زیاد در کنار کار شما خواهد بود که می تواند موجب ایجاد یک بسته های جدید و مجزا شود که بتوانید از آنها در برنامه استفاده کنید. اگرچه این ارتباطی به زبان سی یا سی پلاس پلاس ندارد. اما در جریان باشید که موضوع کامپایل های زمان اجرا موضوعی است که در سال های اخیر در حال کار بوده است و موضوعی است که به نتیجه ی مطلوبی با دید و نگاه عادی نخواهد شد. اگرچه این مورد می تواند در برخی فضا ها بسیار مفید واقع شود. بهرحال در پاسخ دادن و نقد کردن پیام من راحت باشید! مکس بیس / Max Base
  2. Max Base

    موفق باشید. Linux Professional Institute
  3. با سلام وقت بخیر, در این مطلب میخواهیم در مورد روش کارکرد پیام رسان ها بیشتر بدانیم و با یکدیگر کد یک پیام رسان ساده را پیاده و بررسی کنیم. طرز کار کرد پیام رسان در نظر داشته باشید که هر پیام رسانی که بر ساختار ها پیاده شده باشد از دو قسمت تشکیل شده است. نرم افزار اصلی برای مدیریت درخواست ها (سرور) نرم افزار برای کاربران (کاربر) به نرم افزار اولی سمت 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
  4. سلام وقت بخیر, گیت هاب پیج گیتهاب پیج یک سرویس میزبانی وب است که توسط 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
×
×
  • جدید...