কেন সিএসই পড়বা না

এইচএসসি পরীক্ষা শেষে ফলও বেরিয়ে গেছে। এখন বিশ্ববিদ্যালয়ে ভর্তি হওয়ার পালা। আর বাংলাদেশে যেহেতু তথ্য প্রযুক্তি বেশ জনপ্রিয়, তাই নিজের ইচ্ছায় হোক বা অন্যের প্রভাবে, অনেকেই কম্পিউটার সায়েন্স পড়তে চায়। অনেক জায়গায় কম্পিউটার সায়েন্স, কোথাও আবার কম্পিউটার সায়েন্স ও ইঞ্জিনিয়ারিং, কোথাও সফটওয়্যার ইঞ্জিনিয়ারিং – কিন্তু সিলেবাস কাছাকাছিই। আর দেশের মোটামুটি সকল সরকারি বিশ্ববিদ্যালয় ও বেসরকারি বিশ্ববিদ্যালয়গুলোতে এই বিভাগটি রয়েছে। এখন কোনো সিদ্ধান্ত নেওয়ার আগে একটু জেনে-বুঝে সিদ্ধান্ত নিলে ভালো হয়। সেজন্যই আমার এই লেখা।

কম্পিউটার সায়েন্স একটা অদ্ভুত বিষয়। বাংলাদেশে এই বিষয়ে গ্র্যাজুয়েশন করার পরে কেউ কেউ সরাসরি গুগল, ফেসবুক, অ্যামাজন, মাইক্রোসফটে চলে যায়। এছাড়াও এশিয়া ও ইউরোপ-আমেরিকার বিভিন্ন কোম্পানীতেও যায়। এসব জায়গায় একজন ফ্রেশ গ্র্যাজুয়েটের বেতন হয় জায়গাভেদে তিন থেকে সাত লক্ষ টাকা! তাহলে তো সবারই সিএসই পড়া উচিত। কিন্তু আসলে বেশিরভাগ শিক্ষার্থী পাশ করার পরে দশ হাজার টাকা বেতনের চাকরি জোটাতেই হিমশিম খায়, গুগল-ফেসবুক তো অনেক দূরের কথা। দেশের মধ্যেও যারা চাকরি পায়, তাদের কারো কারো বেতন শুরুতে ৫০-৬০ হাজার টাকা। আর কারো কারো বেতন ১০-১৫ হাজার টাকা। এর কারণ কী? এত বৈষম্য কেন? সবই কি মামা-চাচার জোর?

কারণটা হচ্ছে দক্ষতা। কম্পিউটার সায়েন্স পড়ে যারা খুব শীর্ষস্থানীয় ছাত্রছাত্রী, তারা গবেষণা ও উচ্চশিক্ষার জন্য বিদেশে চলে যায়, কিন্তু এরকম তো হাতে গোণা। বাকীদের জন্য কিন্তু সফটওয়্যার ইঞ্জিনিয়ার হওয়া ছাড়া আর খুব ভালো অপশন নাই। যদিও আরো কিছু ক্যারিয়ার রয়েছে, কিন্তু এটাই প্রধান অপশন। তো এই কাজ করার জন্য প্রোগ্রামিং জানা লাগে। আর প্রোগ্রামিংটা ঠিক অন্য লেখাপড়ার মতো নয়, যে খালি পড়ে গেলাম, শিখে ফেললাম। এটা হচ্ছে একটা দক্ষতা, যেটা শিখতে হয়, করতে পারতে হয়। আবার এটা ঠিক ইট ভাঙ্গার মতো দক্ষতাও নয়, এখানে লেখাপড়া লাগে, যুক্তি-বুদ্ধি-বিশ্লেষণ লাগে। তো অসুবিধা কী? আমরা প্রোগ্রামিং শিখে ফেলবো। কিন্তু শিখতে পারবা না, কেন, সেটা বলছি।

প্রোগ্রামিং শিখতে পরিশ্রম করা লাগে – পড়া এবং প্র্যাকটিস করা। আর এই প্র্যাকটিস করার জন্য আবার মাথাও খাটাতে হয়, এটা কিন্তু দেখে দেখে টাইপ করা ধরণের প্র্যাকটিস না। মাঝে-মধ্যে অজানা সমস্যা চিন্তা করে সমাধান করতে হয়। প্রোগ্রামিং শেখার সময় একটা ছোট সমস্যার সমাধান করতে ৪-৫ ঘণ্টা লেগে যায়। তো আমরা কিন্তু ক্লাস ওয়ান থেকে শুরু করে এইচএসসি পর্যন্ত মোটামুটি মুখস্থ করেই পার করে এসেছি। বড়জোর কিছু অঙ্ক হয়তো বোঝার চেষ্টা করেছি। আমাদের কখনওই একটা প্রবলেম করার জন্য ৪-৫ ঘণ্টা সময় দেয়া লাগে নাই। আশা করি, বিষয়টা পরিষ্কার। এখন কথা হচ্ছে, সময় দেওয়া লাগলে দিবো, যত পরিশ্রম করার দরকার করবো, টিচারের সাহায্য নিবো। কথা কিন্তু এখানেই।

প্রথমত, টিচারের সাহায্যের আশা ছেড়ে দাও। বেশিরভাগ জায়গাতেই ভালো টিচার নাই। কারণ প্রোগ্রামিংয়ে যারা খুব ভালো, হাতোগোণা কয়েকজন বাদে কেউ আসলে বাংলাদেশে শিক্ষকতা করে না। তাই আমি অনেকের কাছেই শুনি, ক্লাসে টিচার ঠিকমতো প্রোগ্রামিং বুঝাতে পারে না। চাকরির ইন্টারভিউ যে নিবে, সে তো এটা শুনে বলবে, “তাতে আমার কী?” এখন তুমি ভাবতে পারো, প্রোগ্রামিং তো নিজের চেষ্টাতেও শেখা যায়। আমি নিজে চেষ্টা করে শিখবো। সেটাও হবে না, কেন, জানতে হলে এই লেখার বাকী অংশ পড়।

আসলে, প্রোগ্রামিংয়ের পেছনে তুমি সময় দিতে পারবা না। তোমার ভার্সিটির ক্লাস করা লাগে, আর ঢাকায় থাকলে তো আবার রাস্তা-ঘাটেও অনেক সময় ব্যায় হয়। এছাড়া আমরা সামাজিক জীব, বন্ধুবান্ধব-আত্মীয়স্বজন আছে। কত রকমের প্রোগ্রামে যাওয়া লাগে। এদিকে আবার রাতের বেলায় প্রিমিয়ার লীগ, লা লিগা, উয়েফা – কতকিছু। আর ক্রিকেট খেলা তো আছেই – না দেখলে পাপ হয়। তারপরে আছে কত রকমের সিরিয়াল, গেম অব থ্রোনস, হেন-তেন, না দেখলে সমাজে মান থাকে না। এত কিছুর পরে আবার আছে মোবাইল, ফেসবুক, ম্যাসেঞ্জার, ভাইবার, হোয়াটসঅ্যাপ ইত্যাদি। আমি তো নোটিফিকেশনের কাছে যাই না, নোটিফিকেশন আমার কাছে আসে! এজন্যই বলি, সময় দিতে পারবা না। আর পরিশ্রমও করতে পারবা না, সময় দিতে পারলেই না পরিশ্রম করবা। সুতরাং সময় থাকতে নিজের ভালো বুঝে নাও। কম্পিউটার সায়েন্স পড়ে বেকার থাকার চেয়ে অন্য কিছু কর।

আর কম্পিউটার সায়েন্স কিন্তু অনেক বোঝার বিষয়। যাদের গণিতের সাধারণ বিষয়গুলো বুঝতেই সমস্যা হয়, তাদের আসলে এই দিকে না আসাই ভালো।

যারা আমার কথায় এখনও একমত হও নাই, তারা আমার লেখা প্রোগ্রামিং শেখার একটা বই আছে, (http://cpbook.subeen.com-এ গিয়ে ফ্রি-তে বইটা পড়া যায়)। সেই বইটা কিছুদিন পড়। যদি মনে হয়, এই জিনিস নিয়া আগামী চার বছর ব্যাপক খাটাখাটনি করতে পারবা এবং আগামী ২০-৩০ বছর এইরকম বিদঘুটে জিনিসকেই নিজের পেশা হিসেবে নিতে পারবা, তাহলে কম্পিউটার সায়েন্স পড়লেও পড়তে পারো।

প্রোগ্রামিং ক্লাব

বাংলাদেশে ধীরে ধীরে প্রোগ্রামিং বিষয়টি জনপ্রিয় হয়ে উঠতে শুরু করেছে। প্রোগ্রামিংকে ঘিরে বিভিন্ন পর্যায়ে প্রতিযোগিতা, হ্যাকাথন ইত্যাদি অনুষ্ঠান মাঝে-মধ্যে অনুষ্ঠিত হচ্ছে। এর মাঝে কেউ কেউ আবার নিজেদের উদ্যোগে গঠন করছে বিভিন্ন ক্লাব আর সেখানে শিক্ষার্থীদের প্রোগ্রামিংয়ে আগ্রহী করার জন্য চলে নানান আয়োজন। তো কখনও কখনও অনেকে আমার কাছে জানতে চায় যে, “ভাই, আমি আমার এলাকায় বা স্কুলে একটি প্রোগ্রামিং ক্লাব করতে চাই, কিভাবে কী করবো?” তখন আমি তাদেরকে মিজানুরের কথা বলি। ঝিনাইদহের মিজানুরকে আমি কিভাবে চিনলাম, সেটি জানতে হলে পড়তে হবে এই লেখাটি। মিজানুর কেবল ক্লাব তৈরি করেই ক্ষান্ত হয় নি, তার ক্লাবের ছেলেমেয়েরা জাতীয় হাইস্কুল প্রোগ্রামিং প্রতিযোগিতায় পুরষ্কারও জিতেছে। তো মিজানুরকেও অনেকে একই প্রশ্ন করে, তাই সে গুছিয়ে একটি লেখা লিখেছে। মিজানুর রহমানের লেখাটি এখানে তুলে দিলাম। লেখাটির জন্য মিজানুরকে অশেষ ধন্যবাদ।

আপনি কিভাবে আপনার এলাকায় একটি প্রোগ্রামিং সংগঠন গড়ে তুলবেন?

প্রথমেই প্রোগ্রামিং শেখাতে যাবেন না। গ্রাম/জেলা শহরের প্রায় অধিকাংশ মানুষের ধারনা কম্পিউটার বিনোদন এর কাজে ব্যবহার করা হয়, তাদের কাছে কম্পিউটার এর বিনোদনটাই আনন্দদায়ক। ঠিকাছে, আপনি ১০০ জন শিক্ষাথীকে এক জায়গায় করেন, যদি না পারেন তাহলে ৫০ জন, যারা ষষ্ঠ থেকে নবম শ্রেণীর শিক্ষার্থী। দশম শ্রেণীর শিক্ষাথীদেরকে নিতে হবে না, কারণ তাদের কিছুদিন পরই SSC পরীক্ষা।

তাদেরকে বোঝান কম্পিউটার আসলেই কী? এটি দিয়ে অনেক মজার মজার কাজ করিয়ে নেওয়া যায়, যেমন- কম্পিউটার ১ থেকে ১০০০০০ এর মধ্যে যত মৌলিক সংখ্যা আছে, তা ১ সেকেন্ডে বলে দিতে পারে! অবশ্যই মজা করে এবং আশ্চার্য জনক ভাবে বোঝাতে হবে। তারপর আপনি চাইলে মটিভেশনাল কিছু ভিডিও দেখান। এই ভিডিও গুলা দেখাতে পারেন –

https://www.youtube.com/watch?v=krYXHtrzXLU

https://youtu.be/wldli30PT1E

সর্বপরি প্রথমে তাদের কে এটাই খুব ভালো করে বোঝাতে হবে যে কম্পিউটার বিনোদন এর মেশিন না, এটা অনেক শক্তিধর, যেটা দিয়ে পৃথিবী পৃষ্ঠ থেকে চাঁদে একটা রোবট নিয়ন্ত্রন করা যায় যেন রুপকথার মতন)।

এখন আসি প্রোগ্রামিং-এ, এতক্ষণ ধরে তাদেরকে যেই রূপকথা শোনালেন, সেটার আসল শক্তি যে প্রোগ্রামিং সেটা ভালো করে বোঝান। বোঝান যে, এই প্রোগ্রামিং শিখলে তুমি এক সুপার পাওয়ার এর অধিকারি হতে পারবে, তুমি যে ক্লাশ অফ ক্লান, টেম্পল রান নামক গেম গুলা খেলো সেগুলা বানাতে পারবে। বোঝান যে এই প্রোগ্রামিং শিখলে অনেক সম্মান + পুরস্কার পাওয়া যায় (NHSPC এর ব্যাপার টা)।

এর পর দেখেন সেই ১০০ জন এর মধ্যে কত জন প্রোগ্রামিং এর ব্যাপারে উৎসাহী হয়। আশা করি, অনেকে হবে, কারন আমার অভিজ্ঞতা তাই বলে।

এখন যারা প্রোগ্রামিং এ আগ্রহী, তাদের একটা প্রধান সমস্যা হবে, তাদের অনেকের কোনো ল্যাপটপ বা ডেক্সটপ নাই। তখন আপনি তাদেরকে বলবেন যে, এই প্রোগ্রামিং জিনিসটা এন্ড্রয়েড মোবাইল দিয়েও করা যায়। এমন ফ্যামিলি খুব কম আছে যাদের পরিবারে বাবা, মা অথবা বড় আপু-ভাইয়ার একটা এন্ড্রয়েড মোবাইল নাই। তাই তাদের আটকে থাকার কারণ নাই।

এবার আসি কিভাবে প্রোগ্রামিং শেখাবেন সেই কথায়। আপনি তাদেরকে শুধু শেখান, কিভাবে কোডব্লকস ইনস্টল দিবে, কিভাবে কোড লিখবে, কিভাবে কোড রান কম্পাইল করবে, কোডে কোথাও ভুল থাকলে সেগুলা কিভাবে বুঝবে, কিভাবে কোড রান করবে। এবং পরিশেষে তাদের কে আপনি “Hello World” টা রান করা শিখিয়ে দিন। বাকি সব কিছু তারা শিখে নিবে! কিভাবে? ওদের কে খুব ভালো করে একটা জিনিশ শিখিয়ে দিতে হবে আপনাকে, সেটা হলো তারা নিজেরা কিভাবে বই (বই এর লিংক http://cpbook.subeen.com) পড়ে প্রোগ্রামিং শিখবে। বই-এর প্রতিটা কোড সে নিজে নিজে লিখবে এবং রান করবে। কোথাও না বুঝলে ফেসবুক-এ অনেক গ্রুপ আছে (যেমন : https://facebook.com/groups/programming.school/ অথবা https://facebook.com/groups/bengaliprogramming/ ) সেখানে শিক্ষার্থীরা তাদের সমস্যা বা প্রশ্ন পোস্ট করবে। আর যদি ফেসবুক না থাকে (না থাকাই আসলে ভালো) তাহলে আপনার মোবাইল নাম্বার দিয়ে দিন, আপনাকে ফোন করবে, আপনি ফোনে বুঝায়ে দিবেন, আর গুগল তো আছেই। এখন গ্রামেও খুব ভালো ইন্টারনেট। আর আপনি প্রচুর উৎসাহ দিবেন। ছোটরা আনন্দের সাথে শিখতে ভালোবাসে, তাদেরকে যেটুকুই শেখান না কেন, আনান্দের সাথে শেখান।

এদের মধ্যে কিছু শিক্ষাথী থাকবে, যারা ২/১ দিন শিখে আর শিখতে চাইবে না। তাদেরকে আর শেখানোর চেষ্টা করার দরকার নাই, কাউকে জোর করে কিছু শেখানো যায় না এবং আমি এটার পক্ষে না। সবাইকেই যে প্রোগ্রামিং শিখতে হবে তা নয়। কেউ ক্রিকেট খেলবে, কেউ গান গাবে-শিল্পী হবে, কেউ ডাক্তার হবে। কিন্তু প্রোগ্রামিং এর মতন একটা মজার জিনিশের সাথে তাদের পরিচয় হবে সেটাই আসল কথা।

আমি শতভাগ নিশ্চিত আপনি ১/২ মাস পর ১০/২০ জন শিক্ষাথী পাবেন যারা মোটামুটি প্রোগ্রামিং পারে। এর পর ঐ ১০ জনকে দেখেই আরো ১০ জন শিখবে। তারপর আরো ১০ জন, তারপর আরো…এভাবেই চলবে…।

আপনার জেলা টেকনাফ হোক আর তেতুলিয়া হোক, অথবা সুন্দরবনের মধ্যে আপনার গ্রাম হোক, আপনি আপনার এলাকায় একটা প্রোগ্রামিং সংগঠন তৈরি করতে পারেন। আগামী বিশ্ব না, এই বর্তমান বিশ্ব এখন প্রোগ্রামারদের। আর এই বিশ্বকে শাসন করবে তারা, যাদের প্রোগ্রামার আছে, প্রযুক্তি আছে। আর প্রোগ্রামার তাদেরই থাকবে যারা হাইস্কুল থেকেই শিক্ষাথীদের প্রোগ্রামিং শেখাবে।
হ্যাপি কোডিং </>

– মিজানুর রহমান।

 

ফ্লো চার্ট (Flow Chart)

ফ্লো চার্ট (বাংলায় প্রবাহ চিত্র)-এর নাম আমরা সবাই কমে বেশি শুনে থাকি। এখন ফ্লো চার্ট জিনিসটা কী, এমন প্রশ্ন অনেকের মনেই আসে। ফ্লো চার্ট হচ্ছে এক ধরণের ডায়াগ্রাম বা চিত্র যা কোনো অ্যালগোরিদম, কাজের ধারা বা প্রসেস-কে চিত্রের মাধ্যমে বিভিন্ন জ্যামিতিক চিহ্ন বা symbol দ্বারা প্রকাশ করে এবং সেই জ্যামিতিক চিহ্ন বা symbol গুলো তীরচিহ্ন দ্বারা একে অপরের সাথে যুক্ত থাকে।

ফ্লো চার্টের মাধ্যমে একটি প্রোগ্রামের খুঁটিনাটি অংশগুলো খুব সহজেই বুঝানো যায়। যেমনঃ বাড়ি তৈরি করার সময় একজন আর্কিটেক্ট বাড়ির ডিজাইন করে আমাদের খুব সহজেই দেখাতে পারেন যে বাড়িটির কোথায় কী কী জিনিস থাকবে। ফ্লো চার্টের মাধ্যেমেই এই একই কাজই করা হয়। অর্থাৎ, একটি ফ্লো চার্ট বানানোর উদ্দেশ্য হলো একটি প্রোগ্রাম কীভাবে সমাধান করা হয়েছে, সেটি বিভিন্ন ডায়াগ্রাম বা চিহ্নের সাহায্যে অন্যকে বুঝানো।

ফ্লো চার্টের দুইটি প্রকারভেদ আছেঃ

  • ডাটা ফ্লো চার্ট ।
  • প্রসেস ফ্লো চার্ট।

প্রোগ্রামাররা ডাটা ফ্লো চার্ট ব্যবহার করে থাকে। কোন জায়গা থেকে ডাটা আসছে, ডাটা কিভাবে পরিবর্ধন হচ্ছে এবং কোথায় জমা হচ্ছে এসব চিহ্নিত করার জন্য প্রোগ্রামাররা ডাটা ফ্লো চার্ট ব্যবহার করে।

প্রসেস ফ্লো চার্ট কোন প্রসেস বা কাজকে ডকুমেন্ট আকারে দেখানোর জন্য, একটি কাজের কার্যকারিতা বা efficiency বুঝানোর জন্য, কোন প্রশিক্ষণ বা ট্রেনিং এর জন্য ব্যবহার করা হয়।

ফ্লো চার্ট ছোটখাট প্রসেস বা প্রোগ্রামের জন্য ব্যবহার করা হয়ে থাকে। ফ্লো চার্টে সাধারণত দুই ধরণের বাক্স ব্যবহার করা হয়ঃ

  • প্রসেসিং স্টেপঃ এই ধাপকে এ্যাকটিভিটি বা কার্যক্রম ধাপও বলা হয়ে থাকে। একে আয়তাকার বাক্স দ্বারা প্রকাশ করা হয়।
  • ডিসিশন স্টেপ বা সিদ্ধান্ত ধাপঃ এই ধাপকে ডায়মন্ড বা হীরক আকৃতি দ্বারা প্রকাশ করা হয়।

নিচের ছবিতে আমি একটি ফ্লো চার্টের বিভিন্ন আকৃতির পরিচয় দিয়েছিঃ

table

আমরা একটা ছোট্ট উদাহরণের মাধ্যমে ফ্লো চার্টের ব্যাপারটা বোঝার চেষ্টা করি। ধরা যাক, তুমি একজন সৌখিন মানুষ। তোমার শখ গলফ খেলা। তুমি মনে করলে শুক্রবার গলফ খেলতে বের হবে, যদি আবহাওয়া ভাল থাকে। বাংলাদেশে আজকাল আবার হুটহাট বৃষ্টি চলে আসে। তাই বের হওয়ার আগে তুমি আবহাওয়ার সর্বশেষ খোঁজ খবর নিয়ে বের হবে। এর জন্য তোমাকে প্রথমেই যে কাজটি করতে হবে সেটি হলো আবহাওয়ার চ্যানেলে গিয়ে বা মোবাইলের অ্যাপস থেকে weather forecast দেখতে হবে। তারপর সিদ্ধান্ত নিতে হবে, যদি বৃষ্টি হওয়ার সম্ভাবনা থাকে তাহলে তুমি কী করবে আর না থাকলেই বা কী করবে। বৃষ্টি থাকলে তুমি ঘর থেকে বের হবে না আর বৃষ্টি না থাকলে বের হবে। এখন এই পুরো বিষয়টা যদি আমরা ফ্লো চার্টের মাধ্যমে দেখি তাহলে চিত্রটা হবে এমনঃ

sampfc

এই ফ্লো চার্টটিতে প্রথমেই আমরা ফ্লো চার্টের নিয়মানুযায়ী start দিয়ে শুরু করেছি , ওভাল বাক্স দিয়ে সেটিকে চিহ্নিত করেছি। তারপর আমরা ওয়েদার চ্যানেল দেখার কাজটি করেছি। এখানে আমরা প্রসেসিং এর জন্য আয়তাকার চিহ্ন ব্যবহার করেছি, কারণ এখান থেকেই আমরা আমাদের সিদ্ধান্ত বা ডিসিশন নেয়ার ধাপের দিকে যাবো। পরের ধাপে আছে ডিসিশন বা সিদ্ধান্ত ধাপ। সেখানে লেখা আছে “Rain Predicted?”, এখানে লক্ষ্য করে দেখো, ডিসিশন বা সিদ্ধান্ত ধাপে আমাদের অ্যারো বা তীর চিহ্ন আছে দুইটি; যা yes/no দিয়ে চিহ্নিত করা। যদি yes হয় তাহলে আমরা বলছি “Stay Home” এবং সেখান থেকে আরেকটি অ্যারো দিয়ে ফ্লো চার্টটি Stop করে দিচ্ছি। আবার যদি “Rain Predicted”-এ ডিসিশন হয় no, তাহলে আমরা “Play Golf” এর কাজ প্রসেসিং করে Stop ধাপে চলে যাচ্ছি। এখানে মনে রাখার বিষয় যে, ফ্লো চার্চের ডিসিশন সবসময় হয় ডান-বাম অথবা নিচের দিকে যাবে। কখনো উপরের দিকে যাবে না। কারণ, কোন কিছুর Flow সবসময় উপর থেকে নিচের দিকে আসে।

একটি সহজ প্রোগ্রামিং সমস্যার মাধ্যমে আমরা একটি ফ্লো চার্ট তৈরি করার চেষ্টা করি । ধরা যাক, আমরা দুইটি সংখ্যা যোগ করার জন্য একটি প্রোগ্রাম লিখবো। প্রোগ্রামটি হবে এমনঃ

#include<stdio.h>
int main()
{
    int a,b,total;
    scanf("%d %d", &a, &b);
    total = a + b;
    printf("%d\n",total);
    return 0;
}

প্রোগ্রামটির জন্য আমরা যদি ফ্লো চার্ট লিখি তাহলে হবে এমনঃ

enflowchartm_clip_image004

অন্যান্য ফ্লো চার্টের মতই এটা start দিয়ে শুরু হয়েছে। যেহেতু দুইটি নাম্বার ইনপুট নেয়ার দরকার আছে আমাদের, তাই আমরা এখানে Input A, Input B নিয়েছি এবং সেটিকে সামান্তরিক চিহ্নের মাধ্যমে দেখিয়েছি। তবে, আলাদা আলাদা ভাবে এভাবে ইনপুট না নিয়েও পাশাপাশি Input A,B অথবা Read A,B এভাবেও ফ্লো চার্টে ইনপুট নেয়ার কাজটি দেখানো যায়। তারপর আমরা a,b দুইটি যোগ করে একটি Total ভ্যারিয়েবলে রেখেছি এবং এর পরের ধাপে Total প্রিন্ট করেছি। সবশেষে আমরা stop দিয়ে ফ্লো চার্টটি শেষ করেছি।

এবার যদি আমরা লুপ সংক্রান্ত একটি কোডের কথা চিন্তা করি, যেখানে ১ থেকে ১০০ পর্যন্ত বিজোড় সংখ্যা বের করার প্রোগ্রাম লিখতে হবে। প্রোগ্রামটি হবে এমনঃ

#include<stdio.h>
int main()
{
    int i=0;
    while(i<=100)
    {
        if(i%2 != 0)
        {
            printf("%d\n",i);
        }
        i++;
    }
    return 0;
}

এই প্রোগ্রামটিতে আমরা while লুপের সাহায্যে 100 পর্যন্ত লুপটি চালিয়েছি এবং লুপের ভিতরে বিজোড় সংখ্যা বের করার কন্ডিশন দিয়েছি। বিজোড় সংখ্যা বা odd numbers বের করার জন্য if কন্ডিশনটিতে i এর যেসকল মানকে 2 দ্বারা ভাগ করলে ভাগশেষ শূন্য হবে না সেই সংখ্যাগুলোকে আমরা প্রিন্ট করেছি। এই প্রোগ্রামটির ফ্লো চার্টে আমাদের ডিসিশন স্টেপ আসবে দুইটিঃ একটি while এর জন্য এবং একটি if এর জন্য। ফ্লো চার্টটি নিম্নরূপঃ
odd-numsএখানে প্রথমেই আমরা i এর মান 0 এ্যাসাইন করে দিয়েছি, যেহেতু পরবর্তীতে আমরা i এর মান এক করে ইনক্রিমেন্ট করবো। তারপর আমরা while (i<=100) reached ডিসিশন ধাপে গিয়েছি। খেয়াল করে দেখো, এই ডিসিশন থেকে yes/no দিয়ে দুইটি তীর চিহ্ন বের হয়েছে। আমাদের প্রোগ্রামের লজিক আমাদের বলছে যতক্ষণ না i এর মান ১০০ এর সমান বা এর থেকে ছোট থাকছে , ততক্ষণ আমাদের if(i%2 !=0) কন্ডিশন তার কাজ করে যাচ্ছে এবং odd নাম্বার বা বিজোড় সংখ্যাগুলো প্রিন্ট করে যাচ্ছে। একই সাথে লুপটি সামনে এগিয়ে যাচ্ছে, i এর মান compute i= i+1 এ যেয়ে এক এক করে বৃদ্ধি পাচ্ছে। যখন i এর মান 100 এর বড় হয়ে যাবে, তখন ফ্লো চার্ট stop হয়ে যাবে।

প্রশ্ন আসতে পারে, ফ্লো চার্ট ব্যবহার করার সুবিধা কী? প্রবলেম সল্ভিং এর সময় ফ্লো চার্ট ব্যবহার করে আমরা একটি প্রবলেমকে ছোট ছোট অনেকগুলো সুস্পষ্ট ভাগে ভাগ করতে পারি। অনেক সময় দেখা যায়, প্রোগ্রামিং সমস্যা সমাধান করার সময় আমরা খুব গুরুত্বপূর্ণ কোন কিছু বাদ দিয়ে যাচ্ছি। কিন্তু যদি ফ্লো চার্টের মাধ্যমে আমরা আগে প্রবলেমটি analysis করি তাহলে আমাদের খুঁটিনাটি জিনিস বাদ যাওয়ার সম্ভাবনা কমে। সেইসাথে অতিরিক্ত জিনিস, যা আমাদের প্রোগ্রামের requirements এ নেই, সেগুলো বাদ দেয়ার মাধ্যমে একটি প্রোগ্রামকে আরো বেশি efficient করা যায়।

লেখকঃ তামান্না নিশাত রিনি।

ফ্লোচার্ট নিয়ে ভিডিও লেকচার :

সফটওয়্যার ইঞ্জিনিয়ারিং ইন্টারভিউ

সফটওয়্যার ইঞ্জিনিয়ারিং ক্যারিয়ার নিয়ে ধারাবাহিক তবে বিক্ষিপ্ত একটি সিরিজের প্রথম লেখা এটি। আজকের লেখার মূল বিষয় হচ্ছে ইন্টারভিউতে কোন বিষয়গুলোর ওপর জোর দেওয়া হয়, সেই সম্পর্কে ধারণা দেওয়া। তুমি কোন দেশের নাগরিক, কোন বিশ্ববিদ্যালয় থেকে পাশ করা – সফটওয়্যার ইঞ্জিনিয়ার হিসেবে চাকরি করার জন্য এসব তেমন গুরুত্বপূর্ণ ব্যাপার নয়। যাদের প্রোগ্রামিং ও প্রবলেম সলভিং স্কিল খুব ভালো, তাদের জন্য পৃথিবীর বড় বড় কোম্পানীগুলোর দুয়ার খোলা। আর এরকম কোম্পানী কেবল একটি-দুটি নয়, বরং শতশত কোম্পানী।

ইন্টারভিউ খুব গুরত্বপূর্ণ এ কারণে যে সফটওয়্যার ইঞ্জিনিয়ারিং জবের জন্য তোমার সার্টিফিকেট ও অন্যান্য অভিজ্ঞতা (যেমন প্রোগ্রামিং কনটেস্ট) তোমাকে কেবল ইন্টারভিউ পর্যন্ত পৌঁছাতে সাহায্য করবে। ইন্টারভিউ-তে তুমি কেমন করলে, সেটিই নির্ধারণ করবে যে ওই কোম্পানী তোমাকে নেবে কী না।ইন্টারভিউতে ভালো করতে হলে চাই আলাদা প্রস্তুতি। সাধারণত একটি ইন্টারভিউ হয় ৪০ মিনিট থেকে ৬০ মিনিট। এর বেশিরভাগ সময়ই ব্যায় হয় প্রোগ্রামিং প্রবলেম সলভ করার পেছনে। তো আমরা জেনে নিই যে কোন পাঁচটি বিষয়ের ওপর ইন্টারভিউতে জোর দেওয়া হয়।

১) প্রবলেম সলভিং স্কিলঃ যখন ইন্টারভিউতে তোমাকে একটি প্রবলেম সলভ করতে দেওয়া হয়, তখন দেখা হয় যে তুমি প্রবলেমটি ঠিকভাবে বুঝলে কী না। না বুঝলে প্রয়োজনীয় প্রশ্ন করে সবকিছু পরিষ্কার করে নিলে কী না। সমস্যাটি তুমি কিভাবে বিশ্লেষণ করলে? এটি করতে তোমার কী পরিমাণ সময় লাগল? তোমাকে কতটুকু হিন্টস্ দিতে হয়েছে। এসব বিষয় গুরুত্বপূর্ণ।

২) কোডিং স্কিলঃ যখন তুমি সমস্যা বিশ্লেষণ করে অ্যালগরিদম দাঁড় করালে, সেটির কমপ্লেক্সিটি বের করলে, তারপরে কোনো একটি প্রোগ্রামিং ল্যাঙ্গুয়েজে (সেটা সাধারণত তোমার ইচ্ছামতো) সেই অ্যালগরিদমটি কোড করতে বা ইমপ্লিমেন্ট করতে তোমার কেমন সময় লাগল, ঠিকঠাক ইমপ্লিমেন্ট করতে পারলে কী না – এটিও খুব গুরুত্বপূর্ণ। কোডিং স্টাইল কেমন – ভ্যারিয়েবলের নাম ঠিকঠাক দিলে কী না, কোডিংয়ে ইনডেনটেশন ঠিকমতো করা হয়েছে কী না – এগুলোও বেশ দরকারি জিনিস। আমি নিজে যখন ইন্টারভিউ নেই, তখন কেউ ঠিকমতো কোড ইনডেন্ট না করলে তাকে বাদ দিয়ে দিই।

৩) কম্পিউটার সায়েন্সের মৌলিক জ্ঞানঃ কম্পিউটার সায়েন্সের বেসিক বলতে আমরা বুঝি ডাটা স্ট্রাকচার ও অ্যালগরিদম, ডিজিটাল লজিক, অপারেটিং সিস্টেম, ডাটাবেজ, নেটওয়ার্কিং – এসব মৌলিক বিষয়ের ওপর নূন্যতম ধারণা। তোমাকে বিটওয়াইজ অপারেশন জানতে হবে, থ্রেড ও প্রসেসের পার্থক্য জানতে হবে, রেস কন্ডিশন বুঝতে হবে, রিলেশনাল ডাটাবেজ কী, কেন, নোএসকিউএল কেন প্রয়োজন, এগুলো জানা থাকতে হবে।

৪) অভিজ্ঞতাঃ অভিজ্ঞ প্রার্থীদের ক্ষেত্রে পূর্বে যেসব কোম্পানীতে কাজ করেছ, সেগুলো কেমন, তুমি কোন অংশে কাজ করেছ, সেখানে তোমার অবদান কী – এসব বিষয় বেশ খুঁটিয়ে দেখা হয়। আর ফ্রেশ গ্র্যাজুয়েটদের ক্ষেত্রে প্রোগ্রামিং কনটেস্ট, প্রজেক্ট এসবের অভিজ্ঞতা দেখা হয়। ভার্সিটিতে হয়ত তুমি প্রজেক্ট অন্য কাউকে দিয়ে করিয়ে পার হয়ে যেতে পারবে কিন্তু ইন্টারভিউতে এসে ঠিকই ধরা খাবে। এর জন্য প্রস্তুত থেকো।

৫) সফট স্কিলঃ তোমার টেকনিক্যাল স্কিলের বাইরে তুমি এমনিতে মানুষ কেমন, আচার-ব্যবহার, যোগাযোগের দক্ষতা (কমিউনিকেশন স্কিল) এসবও যাচাই করা হয় (কিন্তু কখন এটা করা হচ্ছে, সেটি তুমি টের পাবে না)। অভিজ্ঞ ইন্টারভিউয়ার কিন্তু ইন্টারভিউ শেষে প্রার্থী সম্পর্কে বেশ কিছু প্রশ্নের উত্তর নিজের মনেই দেয়, সবচেয়ে দরকারি প্রশ্ন হচ্ছে, “আমি কি আমার টিমে এই ব্যক্তির সাথে কাজ করতে খুব খুশি হব?” – উত্তর যদি “না” হয়, তবে চাকরি পাওয়ার কোনো সম্ভাবনা নেই।

সবশেষে বলি, গ্র্যাব (grab.com)-এ আমার বস অরুল (তিনি আগে ১৬ বছর মাইক্রোসফটে ও ৩ বছর অ্যামাজনে কাজ করেছেন) আমাকে ইন্টারভিউ নেওয়ার ক্ষেত্রে একটি সহজ টিপস্ দিয়েছেন। ইন্টারভিউ শেষে নিজেকে প্রশ্ন করতে হবে, “আমার বর্তমান টিমের বেস্ট প্রোগ্রামারকে অন্য টিমের জন্য ছেড়ে দিয়ে এই ছেলেকে (বা মেয়েকে) আমার টিমে নিতে কি আমি রাজি?”

আলফাগো বনাম লি সেডল – কৃত্রিম বুদ্ধিমত্তা এবং মানুষ

ডিপ ব্লু-এর পর এবার আলফাগো। আবারো কম্পিউটারের সঙ্গে খেলে মানুষের হার! ঘটনাটি ঘটেছে দক্ষিণ কোরিয়ার সিওলে। গুগলের ডিপমাইন্ড ইউনিটের তৈরি “গো” খেলার কৃত্রিম বুদ্ধিমত্তার প্রোগ্রাম “আলফাগো” পরপর তিনবার হারিয়ে দিলো ৩৩ বছর বয়সি পেশাদার কিংবদন্তী  “গো” খেলোয়ার লি সিডলকে। পাঁচ ম্যাচ সিরিজের চারটিতেই জিতেছে “আলফাগো”। পরপর তিনবার হারার পর চতুর্থ ম্যাচে এসে জয় পান লি সিডল। এই একটিমাত্র জয়কে তিনি “অমূল্য” হিসেবে গণ্য করেছেন। প্রথম গেমটিতে হারার পর লি সাংবাদিকদের বলেনঃ “আমি খুবই অবাক হয়েছি। আমি হারবো এটা কখনো ভাবিনি। আলফাগো এত ভাল খেলবে এটা আশা করিনি।”

গো অথবা ষোলগুটি বা বাঘবন্দিঃ

“গো” নামক কয়েক হাজার বছরের পুরানো গেমের উদ্ভব হয় চীনে। খেলাটি অনেকটা আমাদের দেশের ষোলগুটি বা বাঘবন্দি খেলার মত। একটি নির্দিষ্ট বোর্ডে সাদা এবং কালো গুটি নিয়ে দুইপক্ষকে খেলতে হয়। উদ্দেশ্য থাকে প্রতিপক্ষের গুটি আটকে বোর্ডের দখল নেয়া। যে বোর্ডের অর্ধেকের বেশি এলাকা দখল করতে পারবে, সেই বিজয়ী। দাবা খেলার সাথে এই খেলার বড় পার্থক্য হচ্ছে, এখানে অসংখ্য সম্ভাবনাময় চাল থাকে। কেবলমাত্র গাণিতিক হিসাব করে সম্ভাব্য চাল বের করা অসম্ভব।

“গো” খেলার জন্য গুগল ডিপমাইন্ড “আলফা-গো” কম্পিউটার প্রোগ্রামটি তৈরি করেছে। এটির অ্যালগোরিদম মেশিন লার্নিং এবং ট্রি সার্চিং প্রযুক্তি সমন্বয়ে করা হয়েছে। এতে পলিসি এবং ভ্যালু নেটওয়ার্ক হিসেবে দুইটি নিউরাল নেটওয়ার্ক আছে। পলিসি নেটওয়ার্কটি সম্ভাব্য সেরা চালটি দ্রত হিসাব করতে পারে এবং ভ্যালু নেটওয়ার্কটি প্রতিটি চালের শুরুতে অপ্রয়োজনীয় চালগুলো বাদ দিয়ে সম্ভাব্য চালের পরিমাণ কমিয়ে ফেলে।মানুষের এই “অপ্রয়োজনীয়” চাল বাদ দেয়ার সক্ষমতায় কৃত্রিম বুদ্ধিমত্তার জোরে অবশেষে ভাগ বসালো আলফাগো। আলফাগো-এর প্রাথমিক পর্যায়ে, একে বিভিন্ন এক্সপার্ট গেমারের ঐতিহাসিক গেমের চালগুলো মনে রাখতে বলা হয়েছিল, ৩০ মিলিয়ন চালের একটি ডাটাবেস থেকে। পরবর্তীতে একটি নির্ধারিত পর্যায়ের দক্ষতা অর্জনের পর রি-ইনফোর্সমেন্ট লার্নিং এর সাহায্যে আলফা-গো-এর সক্ষমতা এমনভাবে বৃদ্ধি করা হয় যে এটি নিজে নিজে খেলার দক্ষতা অর্জন করে।

আলফাগো বনাম লি সেডলঃ

আলফাগো বনাম লি সেডল-এর “গুগল ডিপমাইন্ড চ্যালেঞ্জ ম্যাচ” সিওলে ৯ মার্চ-এ শুরু হয়ে ১৫ মার্চ শেষ হয়। প্রথম ম্যাচটিতে আলফাগো জয়লাভ করে যদিও পুরো ম্যাচের বেশিরভাগ সময় জুড়েই ছিল লি-এর আধিপত্য। কিন্তু শেষ ২০ মিনিটে আলফাগো আধিপত্য বিস্তার করে ম্যাচ জিতে নেয়। মজার ব্যাপার হচ্ছে, খেলার প্রথমদিকে লি  আলফাগো-এর ক্ষমতা যাচাই করার জন্য বেশ বড়সড় একটি ভুল করে বসেন। সেই ভুলের উত্তরে আলফাগো-এর চালটি ছিল একেবারে নিখুঁত এবং কার্যকরী।

চতুর্থ ম্যাচ, যেটিতে লি জয়লাভ করে মানবজাতির মানসম্মান রক্ষা করে, সেখানেও ৭৮ নাম্বার চাল পর্যন্ত আলফাগো-এর জিতে যাওয়ার সম্ভবনা ছিল ৭০%। কিন্তু ৭৯ নাম্বার চালে ভুল করে ফেলার কারণে আলফাগো বঞ্চিত হয় লি সেডলকে হোয়াইটওয়াশ করার সুযোগ থেকে।

১৮টি আন্তর্জাতিক পুরষ্কার বিজয়ী পেশাদার গো খেলোয়ার লি সেডল ম্যাচ শেষে স্বীকার করেন যে শুরুর দিকে তিনি আলফাগো-এর খেলোয়াড়ি দক্ষতাকে অবজ্ঞা করেছিলেন। ডিপমাইন্ডের প্রতিষ্ঠাতা ডেমিস হাসাবিস বলেন, এ পরাজয় মূল্যবান। কারণ, এ থেকে আমরাও আমাদের প্রোগ্রামের দুর্বলতা খুঁজে বের করতে পারবো। “গুগল ডিপমাইন্ড চ্যালেঞ্জ”-এর বিজেতা হিসেবে আলফাগো এক মিলিয়ন ডলার পুরষ্কার জিতে নিয়েছে। ডিপমাইন্ড-এর বিবৃতি অনুযায়ি এই পুরষ্কারের অর্থ ইউনিসেফ, গো অর্গানাইজেশন এবং অন্যান্য দাতব্য প্রতিষ্ঠানে দান করা হবে। ম্যাচ শেষে “সাউথ কোরিয়া গো অ্যাসোসিয়েশন” আলফাগো-কে “গো গ্র্যান্ডমাস্টার” পদবী প্রদান করে।

লেখক : তামান্না নিশাত রিনি।

শিক্ষার্থীদের জন্য অ্যান্ড্রুর উপদেশ

অ্যান্ড্রু এংগ (Andrew Ng) আমার অত্যন্ত প্রিয় একজন শিক্ষক। আজ থেকে প্রায় চার বছর আগে তাঁর মেশিন লার্নিংয়ের ওপর অনলাইন কোর্সটি আমি করেছিলাম। সাস্টে জাফর ইকবাল স্যার যেভাবে ডিসক্রিট ম্যাথ কিংবা ফাইবার অপটিকস্ পড়ান, অ্যান্ড্রুও মেশিন লার্নিংয়ের কোর্স অনেকটা সেভাবেই পড়িয়েছেন। তিনি কোর্সেরা (Coursera)-এর সহপ্রতিষ্ঠাতা এবং বর্তমানে চীনা সার্চ ইঞ্জিন জায়ান্ট বাইডুর রিসার্চ সেকশনের প্রধান বিজ্ঞানী। এছাড়া তিনি বিশ্ববিখ্যাত স্ট্যানফোর্ড বিশ্ববিদ্যালয়ের কম্পিউটার বিজ্ঞান বিভাগের শিক্ষক। সম্প্রতি কোরা (Quora)-তে তিনি কিছু প্রশ্নের উত্তর দিয়েছেন, সেগুলোর মধ্য একটি উত্তর আমি অনুবাদ করে দিলাম। আশাকরি এটা অনেকের কাজে লাগবে।

n-ANDREW-NG-628x314

প্রশ্ন: শিক্ষার্থীদের জন্য আপনার উপদেশ কী?
কোন জিনিসের পেছনে ছুটবে, কী কাজে তোমার মূল্যবান সময় ব্যায় করবে – এই বিষয়ে সিদ্ধান্ত নেওয়ার সময় আমি তোমাকে দুটো জিনিস বিবেচনা করতে বলব –
১) তুমি যেটা করছ বা করতে যাচ্ছ, সেটা সমাজে, কিংবা মানুষের জীবনে কোনো পরিবর্তন আনবে কী না।
২) কাজটি করে তুমি কতটুকু শিখতে পারবে।

এমনকী এখনও আমি কোনো কাজ করার সিদ্ধান্ত নেওয়ার আগে এই দুটো জিনিস বিবেচনা করি।
আমাদের সমাজে অসংখ্য সমস্যা রয়েছে আর তাই সমস্যাগুলোর সমাধান করার জন্য অনেক কিছু করার আছে। বিশেষ করে ডিজিটাল প্রযুক্তি ও যোগাযোগ ব্যবস্থার মাধ্যমে আগের চেয়ে অনেক সহজে কোনো আইডিয়া কিংবা পন্য অনেকের কাছে পৌঁছানো যায়। সঠিক পরিকল্পনা ও সেটার সঠিক বাস্তবায়নের মাধ্যমে একজন মানুষের পক্ষে অনেক অনেক মানুষকে সাহায্য করা সম্ভব। আর এখন তো গণ্ডিটা কেবল নিজের গ্রাম, শহর বা দেশের মধ্যেই সীমাবদ্ধ নয়, সারা পৃথিবীর মানুষের কাছেই ইন্টারনেটের মাধ্যমে পৌঁছানো সম্ভব।

তাই নিজেকে প্রশ্ন কর: তুমি যা করার চিন্তা করছ কিংবা স্বপ্ন দেখছ, সেটি যদি সত্যিই সফলভাবে বাস্তবায়িত হয়, এটি কি অনেক মানুষের জীবনকে প্রভাবিত করবে? অনেক মানুষকে সাহায্য করবে? উত্তর যদি না হয়, তবে অন্য কিছু করার চিন্তা কর। নয়ত তুমি তোমার মাঝে যে অমিত সম্ভাবনা আছে, তার সঠিক ব্যবহার করতে পারবে না।
দ্বিতীয়ত, যখন তুমি তরুণ, নিজের শিক্ষার ব্যাপারে বিনিয়োগ করতে দ্বিধা করবে না। আর হ্যাঁ, আমার কাছে “তরুণ”-এর সংজ্ঞা হচ্ছে যার বয়স ১০০ বছরের কম।

যা কিছুই তুমি আজকে শিখবে, সেটা বাকী জীবনে তোমার অনেক কাজে আসবে। কিন্তু এটি খুব সহজ কাজ নয়। বিশেষ করে তুমি যখন প্রাতিষ্ঠানিক শিক্ষার পাট চুকিয়ে কর্মজীবনে প্রবেশ করবে, তখন কোনো কিছু শেখার পেছনে সময় ব্যায় করে খুব দ্রুত কোনো ফল পাবে না। তোমার সামনে কোনো পরীক্ষা থাকবে না কিংবা কোনো শিক্ষকও তোমাকে পড়ার জন্য তাড়া দেবে না। কিন্তু তুমি যদি নিজেই নিজেকে অনুপ্রাণিত করতে পার, পড়ার মাঝে আনন্দ খুঁজে পাও, নতুন আইডিয়া নিয়ে চিন্তা কর, অন্য মানুষদের সাথে আলাপ-আলোচনায় অংশগ্রহন কর (যাদের কাছ থেকে তুমি কিছু শিখতে পার), তাহলে তুমি যে বিষয়ে জ্ঞান ও দক্ষতা অর্জনের চেষ্টা করছ, কয়েক বছরের মধ্যেই সে বিষয়ে তুমি দক্ষ হতে পারবে। লক্ষ কর, কয়েক সপ্তাহ কিংবা কয়েক মাস নয়, কয়েক বছর।
আমার নিজের কথা যদি বলি, আমি পড়তে পছন্দ করি। আমার কিন্ডেলে (ইবুক পড়ার যন্ত্র) এক হাজারেরও বেশি বই আছে। আমি প্রতি রাতে এবং সপ্তাহের ছুটির দিনগুলোতে বই পড়ার পেছনে প্রচুর সময় দেই। একাডেমিক রিসার্চ পেপার, ব্যবসা পরিকল্পনা, ইনোভেশন, জীবনী – আরো অনেক রকমের বই পড়ি। মাঝে মাঝে অনলাইন কোর্স করি। এছাড়া পুরনো কিংবা নতুন বন্ধুদের সাথে আড্ডা দিতেও অনেক ভালোবাসি এবং তাদের কাছ থেকেও অনেক কিছু শিখতে পারি।

শিক্ষা গ্রহনের প্রক্রিয়াটাও তোমাকে সিদ্ধান্ত গ্রহন করতে সাহায্য করবে যে কী নিয়ে তুমি কাজ করবে। যখন তুমি এমন অনেক উদাহরণ দেখবে যে অন্যরা কীভাবে সমাজ বদলাচ্ছে, তুমি নিজেও অনেক আইডিয়া পাবে যে তুমি কীভাবে দিন বদলের সংগ্রামে যোগ দিতে পার।

আমার বক্তব্যের সারকথা যদি বলি: নিজের শিক্ষায় বিনিয়োগ করতে হবে (সেটা সময় বিনিয়োগ হতে পারে কিংবা অর্থ), এমনকী কষ্ট হলেও সেটা করতে হবে। আর সবসময় সুযোগের সন্ধান করতে হবে যে কীভাবে তুমি এমন কাজ করতে পার যা অন্যকে সাহায্য করবে, সমাজকে বদলে দিবে, পৃথিবীকে বদলে দিবে।

অফ-বাই-ওয়ান এরর (Off-by-one error)

“There are two hard things in Computer Science: Cache invalidation, naming things and off-by-one error”  

উপরের লাইনটি কম্পিউটার বিজ্ঞানের খুব জনপ্রিয় একটি জোক। প্রথম প্রথম যখন আমি প্রোগ্রামিং শেখা শুরু করি, প্রোগ্রাম সফলভাবে কম্পাইল করলেই খুব মজা লাগতো। ইনপুট/আউটপুট দেয়ার পর যখন দেখতাম কোড ঠিকমত কাজ করছে না, তখন আবার চুপসে যেতাম। এমন সমস্যার মুখোমুখি আমরা সবাই হই। লজিকের সমস্যা হলে এমনটি হয়ে থাকে। এমন একটি লজিক্যাল এরর হচ্ছে অফ-বাই-ওয়ান এরর।

অফ বাই ওয়ান এরর কী

“অফ-বাই-ওয়ান এরর” সাধারণভাবে “অফ-বাই-ওয়ান বাগ” নামেও পরিচিত। সংক্ষেপে একে OBOE (Off By One Error ) বলা হয়ে থাকে। যখন কোন লুপের বাউন্ডারি কন্ডিশনে আমরা ভুল করি তখন এই এরর দেখা দেয়। বেশিরভাগ সময় এই এররটি হয় যখন আমরা “is less than equal” (<=) অপারেটরটি কোন তুলনা বা comparison-এর জন্য ব্যবহার করে থাকি বা যখন একটি সিকোয়েন্স শূন্য থেকে শুরু হওয়ার বদলে এক থেকে শুরু হয়।

প্রোগ্রামিং -এ যখন একটি iterative লুপ একই সময়ে কম বা বেশি সময় ধরে চলে তখন অফ বাই ওয়ান এরর সমস্যাটি দেখা দেয়। অর্থাৎ, যদি আমরা n পর্যন্ত কোনো একটি লুপ চালাতে চাই কিন্তু সেটিকে লেখার সময় বাউন্ডারি কন্ডিশন  n+1 অথবা n-1 দিয়ে দেই। অ্যারের কাজ করার সময় আমরা অনেকসময় লুপের মান শূন্য থেকে শুরু করার পরিবর্তে এক থেকে শুরু করি। পরবর্তীতে যখন আমরা অ্যারের উপাদানগুলো প্রিন্ট করতে যাই, দেখা যায় একটি অতিরিক্ত সংখ্যা প্রিন্ট হচ্ছে।

অ্যারের লুপের অফ-বাই-ওয়ান এরর

ধরা যাক, আমাদের পাঁচটি উপাদানের একটি অ্যারে দেয়া আছে। আমরা যদি অ্যারের উপাদানগুলো প্রিন্ট করতে চাই তাহলে আমাদের একটি লুপ চালাতে হবে যেটি অ্যারের পাঁচটি উপাদান ঠিকঠাক প্রিন্ট করে। যদি আমরা এভাবে কোডটি লিখিঃ

Untitled

এখানে লুপটি 0 থেকে শুরু  করে 0,1,2,3,4,5 এভাবে ছয়টি iteration সম্পন্ন করছে। যেটি অ্যারে সাইজ n-কে অতিক্রম করেছে। অ্যারের ক্ষেত্রে আমরা এটিকে “অ্যারে বাউন্ড এক্সেপশন” বলে থাকি। অফ-বাই-ওয়ান এরর-এর কারণে এমনটি হয়ে থাকে।  এখানে for loop-টি n+1 সংখ্যক বার চলেছে। কিন্তু যদি আমরা লুপটির end condition-এ “<=” এর পরিবর্তে “<” ব্যবহার করি, তখন আমাদের লুপটি 0,1,2,3,4 এভাবে মোট পাঁচটি iteration সম্পন্ন করে n সংখ্যকবার চলবে।

তবে, সি++ এর ক্ষেত্রে “আউট অফ বাউন্ড এক্সেপশন” থ্রো করে না। বিগিনারদের এটি বেশ ঝামেলায় ফেলে। তখন দেখা যায়, অ্যারে সাইজ ছোট নেয়ার পরেও কোন রান টাইম এরর দেখায় না।

ফেন্সপোষ্ট এরর

ফেন্সপোষ্ট এরর যা টেলিগ্রাফ পোল বা ল্যাপপোষ্ট এরর নামেও পরিচিত। এটিও একপ্রকার অফ-বাই-ওয়ান এরর। ফেন্সপোষ্ট এররে একটি প্রশ্ন করা হয়ে থাকে যে, যদি একটি সোজা বেড়ার n সংখ্যক ভাগ থাকে তাহলে মোট কতটি পোষ্ট সেখানে আছে।

598px-Fencepost_error.svg

প্রশ্নটির উত্তর যদি 10 বলা হয় তাহলে উত্তরটি হবে ভুল। যদি n+1 সংখ্যক পোষ্ট দিয়ে একটি বেড়া তৈরি করা হয় তাহলেই আমরা n সংখ্যক ভাগ পাবো সেই বেড়াটির। উপরের ছবিটি দিয়ে ব্যাপারটি বুঝানো হয়েছে।

 লেখক: তামান্না নিশাত রিনি।

এক ঘণ্টার পাইথন কোডিং

পাইথন হচ্ছে একটি প্রোগ্রামিং ভাষা। বর্তমান তথ্যপ্রযুক্তির দুনিয়ায় এর ব্যবহার দিন দিন বাড়ছে। প্রফেশনাল কাজের পাশাপাশি প্রোগ্রামিং শেখার জন্যও পাইথন খুবই জনপ্রিয়। পাইথন নিয়ে বিস্তারিত জানা যাবে এই লেখায়: পাইথন কী?

তো সামনে “কম্পিউটার বিজ্ঞান শিক্ষা সপ্তাহ” উদযাপনের একটি গুরুত্বপূর্ণ অংশ হচ্ছে “আওয়ার অব কোড“। সারা পৃথিবীর সাথে সাথে বাংলাদেশেও এটি বেশ ঘটা করে পালন করার উদ্যোগ নিয়েছে বিডিওএসএন, আর সাথে গত দুই বছরের মতো এবারেও আছে দ্বিমিক কম্পিউটিং। অনুষ্ঠানের বিস্তারিত জানা যাবে এই ওয়েবসাইটে : http://cseweek.bdosn.org

বেশিরভাগ মানুষই code.org ওয়েবসাইটে যেই গেমটি দেওয়া আছে, সেটি ব্যবহার করে ‘আওয়ার অব কোড’ পালন করবে। তবে সবার জন্য এটি উপভোগ্য কিংবা উপকারি না ও হতে পারে। বাংলাদেশের প্রেক্ষাপটে কেউ যদি ষষ্ঠ শ্রেণী বা তার ওপরের ক্লাসের শিক্ষার্থীদের নিয়ে এক ঘণ্টার কোডিং করতে চান, আমার পরামর্শ হবে পাইথন ভাষা ব্যবহার করে কয়েকটি প্রোগ্রাম লিখে দেখানোর।

প্রথমেই শিক্ষার্থীদের বলতে হবে, প্রোগ্রামিং কেন শিখবে। তাদের সাথে প্রোগ্রামিং ও প্রোগ্রামারদের নিয়ে গল্প করতে হবে। গল্প-স্বল্প বলা শেষ হলে শুরু করতে হবে এক ঘণ্টার পাইথন কোডিং

১) প্রথম কাজ হচ্ছে সবার কম্পিউটারে পাইথন সফটওয়্যার ইনস্টল করা। ইনস্টলার আগে থেকে ডাউনলোড করে রাখতে হবে (যদি উইন্ডোজ অপারেটিং সিস্টেম হয়, লিনাক্সে এটি এমনিতেই ইনস্টল করা থাকে)। সবাই নিজে নিজে কম্পিউটারে পাইথন ইনস্টল করবে।

২) দ্বিতীয় কাজ হচ্ছে “Hello World” প্রোগ্রাম লেখা। এটি যে প্রোগ্রামিং সংস্কৃতির একটি অংশ, সেটি শিক্ষার্থীদের জানাতে হবে।

৩) 1 থেকে 100 পর্যন্ত সমস্ত পূর্ণসংখ্যা প্রিন্ট করার প্রোগ্রাম দেখাতে হবে। প্রথমে কেবল while লুপ ব্যবহার করে। তারপর for লুপ এবং range() ফাংশন ব্যবহার করে। লুপের ধারণা দিতে হবে। ফাংশন নিয়েও কিছু কথা বলতে হবে। তবে বেশি কথা বলে শিক্ষার্থীদের বিরক্ত করা যাবে না।

৪) এবারে লুপ নিয়ে আরো খেলাধূলা করতে হবে। 1, 3, 5, …, 99 প্রিন্ট করা ও 2, 4, 6, …, 98, 100 প্রিন্ট করার প্রোগ্রাম দেখাতে হবে। তবে এর আগে শিক্ষার্থীদের ১০-১৫ মিনিট সময় দিলে ভালো হয় যেন তারা নিজেরা কাজটি করার চেষ্টা করে। তারপর সংখ্যাগুলোকে বড় থেকে ছোট ক্রমেও প্রিন্ট করার প্রোগ্রাম দেখাতে হবে। শুধু লুপ ব্যবহার করে একবার দেখাতে হবে, তারপর range() ফাংশন ব্যবহার করে।

৫) এবারে কন্ডিশনাল লজিকের ধারণা দিতে হবে। এর জন্য আবার 1 থেকে 100 পর্যন্ত জোড়সংখ্যা ও বিজোড় সংখ্যা প্রিন্ট করার প্রোগ্রাম দেখাতে হবে।

৬) 1 থেকে 1000 এর মধ্যে সমস্ত পূর্ণবর্গ সংখ্যা (1, 4, 9, 16 …) প্রিন্ট করার প্রোগ্রাম দেখাতে হবে। প্রোগ্রামটি একাধিকভাবে লিখে দেখাতে হবে।

৭) লিস্টের ব্যবহার দেখাতে হবে। এর জন্য নিচের তিনটি প্রোগ্রাম দেখালে ভালো হয়:

day = raw_input()
if day in ["Friday", "Saturday"]:
   print day, "is holiday"
else:
   print day, "is not a holiday"
name = raw_input()
if name in ["Rose", "Tulip", "Lily", "Daffodil"]:
   print name, "is a flower"
elif name in ["Mango", "Jackfruit", "Guava", "Papaya"]:
   print name, "is a fruit"
else:
   print "I don't know!"
while True:
   name = raw_input()
   if name == "Exit":
      break
   if name in ["Rose", "Tulip", "Lily", "Daffodil"]:
      print name, "is a flower"
   elif name in ["Mango", "Jackfruit", "Guava", "Papaya"]:
      print name, "is a fruit"
   else:
      print "I don't know!"

৮) সময় থাকলে ডিকশনারির ব্যবহারও দেখানো যায়। দেশের নাম ইনপুট দিলে রাজধানীর নাম আউটপুট দিবে, এমন একটি প্রোগ্রাম লিখতে হবে। তবে খেয়াল রাখতে হবে যে অনুষ্ঠানের কোডিংয়ের অংশ কোনোভাবেই এক ঘণ্টার বেশি করা যাবে না।

সবাইকে অংশগ্রহনের জন্য সার্টিফিকেট দিলে সবাই হয়ত উৎসাহ পাবে।

পাইথনের জন্য কিছু লিঙ্ক:
১) হুকুশ-পাকুশের প্রোগ্রামিং শিক্ষা : http://hukush-pakush.com
২) Hour of Python : https://hourofpython.com
৩) পাইথনের ওপর ফ্রি ভিডিও লেকচার: http://pyvideo.subeen.com
৪) পাইথনের ওপর বাংলায় লেখা বই : http://bit.ly/pybook (প্রোগ্রামিংয়ে একেবারে নতুনদের জন্য উপযোগি নয়)।

সি দিয়ে ওয়েব সার্ভার

এসো নিজে করি : ওয়েব সার্ভার

লেখক : ওমর শেহাব

এটি একটি শিশুতোষ লেখা। যারা মাত্র সি প্রোগ্রামিং শেখা শুরু করেছে তাদের জন্য এটি লিখছি যাতে তারা সি ল্যাংগুয়েজের সামর্থ্য সম্পর্কে কিছুটা ধারণা পায়।

আজকে থেকে এগার বছর আগের কথা। আমি তখন শাবিপ্রবি কম্পিউটার বিজ্ঞান ও প্রকৌশল বিভাগে তৃতীয় বর্ষে পড়ছি। আমাদের একটা কোর্স ছিল সিএসই ৩৫০। এই কোর্সে একটি সফটওয়্যার বানাতে হত। তখন আমার শিক্ষক শাহরিয়ার ভাইয়ের কাছ থেকে সি ল্যাংগুয়েজ দিয়ে একটি ওয়েব সার্ভার বানানোর আইডিয়া পেলাম।

ওয়েব সার্ভার বানানো নতুন কোন ব্যাপার না। ইতিমধ্যেই বাজারে তখন ফ্রি ওপেনসোর্স অ্যাপাচি সার্ভার পাওয়া যেত। শাহরিয়ার ভাই একই বছর অপারেটিং সিস্টেম ক্লাশে মালটিথ্রেড প্রোগ্রামিং, থ্রেড স্কেজ্যুলিং এসব পড়িয়েছিলেন। তার মতে এই প্রজেক্ট করলে আমি যা থিওরী পড়েছি সেগুলো হাতে কলমে নাড়াচাড়া করতে পারব। আমার মনে হল বুদ্ধিটা খারাপ না।

সেই কোডটি এই লিংকে (http://bit.ly/1GEzoX7) পাওয়া যাবে। আমি ভাবলাম যারা মাত্র সি শেখা শুরু করেছে তাদের কেউ কেউ এই ব্যাপারে আগ্রহী হতে পার। আমি একটু একটু করে এই কোডের ব্যাপারগুলো ধরিয়ে দিব। একটি জিনিস মনে রাখতে হবে আমি তখনও ছাত্র ছিলাম এ কারণে কোডের মান খুব বেশি আহামরি না।

তাহলে শুরু হোক! আমি একটি একটি করে ব্লক দিব আর তার নিচে ওই ব্লক নিয়ে কথা বলব।

/*
 * Course Code 350
 *
 * A Multithreaded Tiny HTTP Server
 * Demonstrating Thread Pool Management
 * Following the Thread Pool Management
 * Outline from Unix Network Programming Vol 1
 * by W. Richard Stevens.
 *
 * Project accomplished by: Abu Mohammad Omar Shehab Uddin Ayub
 * Reg No. 2000 330 096
 * Section B
 * 3rd Year 2nd Semester
 * Dept of CSE, SUST
 *
 * Idea and guided by: Mahmud Shahriar Hussain
 * Lecturer
 * Dept of CSE, SUST
 *
 * Course Instructor: Rukhsana Tarannum Tazin
 * Lecturer
 * Dept of CSE, SUST
 */

যারা ইতিমধ্যে প্রোগ্রামিং শুরু করেছ তারা নিশ্চয়ই জান যেকোন কোডের আগে কমেন্টে এই কোডের উদ্দেশ্য ও প্রোগ্রামারের নাম দেয়া স্বাভাবিক ভদ্রতা।

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

সি ল্যাংগুয়েজের নিজস্ব যে ফিচার বা সাপোর্ট আছে সেগুলো বিভিন্ন হেডার ফাইলে কোড করা থাকে। যেমন আমি পোসিক্স থ্রেড নিয়ে কাজ করতে চাই কাজেই পিথ্রেড.এইচ ফাইলটি ব্যবহার করছি।

#define MAX_CLIENT 5
#define MAX_THREAD 3
#define MAX_REQ_HEADER 10
#define MAX 10
#define MAX_LENGTH 6
#define MIME_LENGTH 20

এখানে আমি আগে থেকে কিছু জিনিস ঠিক করে নিচ্ছি। যেমন: আমি চাই এক সাথে পাঁচটির বেশি ব্রাউজার (ফায়ারফক্স, ক্রোম এগুলোকে ব্রাউজার বলে) আমার সার্ভারের পেজ ব্রাউজ করতে পারবে না কাজেই আমি MAX_CLIENT 5 দিয়েছি।

এর পর আমি আমার পছন্দ মত কিছু ডেটা স্ট্রাকচার ঠিক করে নিব।

typedef struct {
   pthread_t threadID;
   long threadCount;
}Thread;

যেমন থ্রেড সম্পর্কিত তথ্য রাখার জন্য আমি থ্রেড নামে একটি স্ট্রাকচার ব্যবহার করছি।

typedef struct {
   char hostName[100];
   char filePath[100];
}Request;

কোন ব্রাউজার থেকে যখন কেউ একটি ওয়েবপেইজ দেখার অনুরোধ সার্ভারের কাছে পাঠাবে সেই অনুরোধটিকে রিকোয়েস্ট নামে একটি স্ট্রাকচারে রাখব। এখানে কোন সার্ভার থেকে অনুরোধটি এসেছে এবং কোন ওয়েব পেজটি দেখতে চাচ্ছে এই তথ্যগুলো থাকবে।

typedef struct{
   int code;
   char date[30];
   char server[30];
   char last_modified[30];
   long content_length;
   char content_type[10];
   char file_path[80];
}Reply;

যখনই কোন ব্রাউজার ব্যবহার করে কেউ একটি পেজ দেখতে চাইবে তার জন্য ঠিকঠাক মতো জবাব তৈরি করা হবে। পেজটি থাকলে সেটি পাঠানো হবে আর না থাকলে বলা হবে পেজ নেই। এর জন্য বেশ কিছু তথ্য পাঠাতে হয়। এগুলো রিপ্লাই নামে একটি স্ট্রাকচারের মাধ্যমে গুছিয়ে পাঠানো হয়।

Thread thrdPool[MAX_THREAD];
Request request[MAX_THREAD];
Reply reply[MAX_THREAD];
int clntConnection[MAX_CLIENT], clntGet, clntPut;

এখানে আমি আমার সার্ভারের লোড নেবার সামর্থ‌্য ঠিক করে দিচ্ছি। লোড মানে সে একসাথে কয়জন ওয়েব ব্যবহারকারীর রিকোয়েস্ট সামলাতে পারবে।

thread_mutex_t clntMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t srvrMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t srvrMutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t emitMutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t clntCondition = PTHREAD_COND_INITIALIZER;

মিউটেক্স জিনিসটা হল মালটিথ্রেডেড প্রোগ্রামিংয়ে অনেকটা ছিটকিনির মত কাজ করে। একটি ওয়েবসার্ভারের কাছে যখন কোন পেজ দেখার রিকোয়েস্ট আসে তখন সে সেটি নিয়ে সারাক্ষণ ব্যস্ত থাকে না। সে কি করে একটি থ্রেড তৈরি করে সেই থ্রেডের কাছে সেই রিকোয়েস্টের দায়িত্ব দিয়ে নিজে নতুন রিকোয়েস্টের জন্য অপেক্ষা করতে থাকে। নতুন রিকোয়েস্ট আসলে সেটিকে নতুন আরেকটি থ্রেডের কাছে পাঠিয়ে দেয় আর আবারো সে আরেকটি রিকোয়েস্টের জন্য অপেক্ষা করতে থাকে। থ্রেডগুলো অপারেটিং সিস্টেমের সাহায্য নিয়ে নিজের মত করে রিকোয়েস্ট পরে পরে যে ওয়েবপেজটি দেখতে চাওয়া হয়েছে সেটি পাঠিয়ে দেয়। একটি থ্রেড কখনও জানতে পারে না অন্য থ্রেডের ভিতরে কি চলছে। তাদের সবার নিজস্ব জগৎ থাকে। তবে সবগুলো থ্রেডকে লাইনে রাখার জন্য কিছু কোড আছে, কিছু ভ্যারিয়েবল আছে। সেই ভ্যারিয়েবলগুলো সব থ্রেড দেখতে পারে। এখন একই ভ্যারিয়েবল নিয়ে যদি একাধিক থ্রেড একই সময়ে কাজ করতে চায় তাহলে তো ভজঘট লেগে যাবে। এখানেই মিউটেক্স কাজে আসে। কোন থ্রেড যখন কোন শেয়ারড ভ্যারিয়েবল নিয়ে কাজ করে মিউটেক্স বা ছিটকিনি তুলে দেয়। অন্য থ্রেড যখন কাজ করতে গিয়ে দেখে ছিটকিনি তোলা তখন তারা চুপচাপ অপেক্ষা করে। শেয়ারড ভ্যারিয়েবল নিয়ে কাজ শেষ হলে সেই থ্রেড ছিটকিনি বা মিউটেক্স নামিয়ে দেয়। তখন অপেক্ষা করতে থাকা অন্য থ্রেড কাজ শুরু করে আর আবারও ছিটকিনি তুলে দেয়।

static int numThreads;
void *request_handler(void *arg);
int find_method (char *req);
Request parse_request(char *rbuff);
Reply prepare_reply(int code, Request rq);
char *getMimeType(char *str);
void emit_reply(int conn, Reply rply);

একটু গুছিয়ে কাজ করার জন্য পুরো কোডটিকে আমি কিছু ফাংশনে ভাগ করেছি। এখানে সেগুলো ডিক্লেয়ার করলাম।

int main(void)
{

মেইন ফাংশন শুরু হল অর্থাৎ প্রোগ্রামের মূল অংশটি শুরু হচ্ছে।

int i, serverSockfd, clientSockfd;
int serverLen, clientLen;
struct sockaddr_in serverAddress, clientAddress, tempAddress;

কাজের সুবিধার জন্য কিছু ভ্যারিয়েবল দরকার।

//defining number of threads
 numThreads = MAX_THREAD;
// initializing queue parameters
 clntGet = clntPut = 0;

একবারে একসাথে কয়টি রিকোয়েস্ট নিয়ে কাজ করা যাবে অর্থাৎ সার্ভারের সামর্থ ঠিক করে দিচ্ছি।

//creating all the threads
for(i = 0; i < numThreads; i++)
{
    pthread_create(&thrdPool[i].threadID, NULL, &request_handler, (void *) i);
} // end of for loop

যখনই কোন রিকোয়েস্ট আসবে একটি করে থ্রেড তার দায়িত্ব নিবে। রিকোয়েস্ট আসার পরপর নতুন থ্রেড তৈরি করতে গেলে প্রোগ্রাম স্লো হয়ে যায় তাই আগেই কিছু তৈরি করে রাখি।

//creating the socket descriptor
serverSockfd = socket(AF_INET, SOCK_STREAM,0);
if(serverSockfd < 0)
{
   error("\nError opening socket");
   exit(1);
}
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons(80);
serverLen = sizeof(serverAddress);
if(bind(serverSockfd, (struct sockaddr *)&serverAddress, serverLen) < 0)
{
   printf("\nError in binding.");
   exit(1);
}

অন্য যেকোন ওয়েবসার্ভারের মত আমার সার্ভারও কম্পিউটারের ৮০ নম্বর পোর্টে কান পেতে রাখবে। এখন আমার জানা জরুরী যে ইতিমধ্যে এই পোর্ট অন্য কোন সফটওয়্যার দখল করে ফেলেছে কিনা। সাবধানের মার নাই!

listen(serverSockfd, 10);

আমি কাআআআন পেতেএএএ রইইই!

for( ; ; )
{
   fflush(stdout);
   //printf("\nWaiting for clients...");
   clientLen = sizeof(tempAddress);
   //printf("\n\nBlocked on accept()");
   clientSockfd = accept(serverSockfd, (struct sockaddr *)&clientAddress, &clientLen);
   //printf("\nAllocated client descriptor# %d", clientSockfd);
   pthread_mutex_lock(&srvrMutex);
   clntConnection[clntPut] = clientSockfd;
   if(++clntPut == MAX_CLIENT)
   clntPut = 0;

   if(clntPut == clntGet)
   {
      printf("\nCan't handle any more request...\nTerminating...");
      exit(1);
   }

   pthread_cond_signal(&clntCondition);
   pthread_mutex_unlock(&srvrMutex);
   fflush(stdout);

} // end of infinite for loop

ইনফিনিটি লুপ খুব একটা ভাল জিনিস না। এটি আরো ভাল ভাবে করতে পারা উচিৎ। এখানে আমি যখনই কোন রিকোয়েস্ট পাচ্ছি ছিটকিনি তুলে দিয়ে একটি থ্রেড ধরে এনে তাকে রিকোয়েস্টের দায়িত্ব দিয়ে দিচ্ছি। যদি দেখি যে ইতিমধ্যে অনেক রিকোয়েস্ট জমে গেছে ভদ্রভাবে না করে দিচ্ছি। তারপর আবার ছিটকিনি বা মিউটেক্স নামিয়ে দিচ্ছি।

} // end of main

মেইন ফাংশন শেষ!

কোন থ্রেড যখন একটি রিকোয়েস্ট পায় তখন রিকোয়েস্ট হ্যান্ডলার নামে একটি ফাংশনের মাধ্যমে সেটি সামলায়। এখন আমরা সেই ফাংশনটি দেখব।

void *request_handler(void *arg)
{

রিকোয়েস্ট ‌হ্যান্ডলার শুরু হল।

int connfd;
char *reqBuff;
fflush(stdout);
//printf("\nThread %d starting", (int) arg);

এক আধটু ভ্যারিয়েবল সব জায়গাতেই লাগে!

for( ; ; )
{
   pthread_mutex_lock(&clntMutex);
   //printf("\nMutex locked by thread# %d.", (int) arg);
   while(clntGet == clntPut)
   pthread_cond_wait(&clntCondition, &clntMutex);

আবারও ইনফিনিটি লুপ ব্যবহার করছি, দু:খিত! আমি এখন শেয়ারড ভ্যারিয়েবলগুলো ব্যবহার করছি কাজেই মিউটেক্স বা ছিটকিনি লাগছে।

connfd = clntConnection[clntGet];
if(++clntGet == MAX_CLIENT)
clntGet = 0;

সার্ভার ওভারলোড হয়ে যাচ্ছে কিনা সেটাও খেয়াল রাখতে হচ্ছে।

// thread operation
// printf("\nIn between mutex lock-unlock. Thread# %d, Connection# %d", (int) arg, connfd);
reqBuff = (char *) malloc (1000);
read(connfd, reqBuff, 1000);

এক একটি রিকোয়েস্টের জন্য কি পরিমাণ রেম (RAM) খরচ হবে সেগুলো ঠিক করছি।

int temp;
temp = find_method(reqBuff);

কোন ব্রাউজার যখন রিকোয়েস্ট পাঠায় তার ভিতরে মেথড বলে একটি জিনিস বলা থাকে। এটি গেট মেথড হতে পারে, পুট মেথড হতে পারে অথবা বাজে ব্রাউজার হলে অর্থহীন কিছু পাঠাতে পারে। এই মেথডটি কি সেটি আমি বের করছি। আমার সার্ভার শুধু গেট মেথড সামলাতে পারে, অন্য কোন মেথড হলে ভদ্রভাবে না করে দেয়।

if(temp == 0)
{
   //printf("\nfind_method returned 0");
   request[(int)arg] = parse_request(reqBuff);
   //printf("\nHost: %s\nFile Path: %s", request[(int)arg].hostName, request[(int)arg].filePath);
   reply[(int)arg] = prepare_reply(200, request[(int)arg]);
   printf("\n\nprinting the reply structure");
   //printf("\nCode: %d\nDate: %s\nServer: %s\nlast_modified: %s\ncontent_length: %ld\ncontent type: %s\nfile path: %s",   reply[(int)arg].code, reply[(int)arg].date, reply[(int)arg].server, reply[(int)arg].last_modified, reply[(int)arg].content_length, reply[(int)arg].content_type, reply[(int)arg].file_path);
   emit_reply(connfd, reply[(int)arg]);
}

এটি গেট মেথড তাই কাজে নেমে পড়ছি।

else if(temp == 1)
{
   printf("\nfind_method returned 1");
   reply[(int)arg] = prepare_reply(501, request[(int)arg]);
   emit_reply(connfd, reply[(int)arg]);
}

এটি পুট বা অন্য কোন স্বীকৃত মেথড যার সাপোর্ট আমি দিইনি। দু:খিত!

else
{
   printf("\nfind_method returned -1");
   reply[(int)arg] = prepare_reply(400, request[(int)arg]);
   emit_reply(connfd, reply[(int)arg]);
}

আজগুবি মেথড।

pthread_mutex_unlock(&clntMutex);
//printf("\nMutex unlocked by thread# %d.", (int) arg);
thrdPool[(int) arg].threadCount++;

ছিটকিনি!

   // shahriar bhai told that closing the connection formally is not so important
   // good performance achieved @ closing it formally
   close(connfd);
}

যখনই কোন রিসোর্স ব্যবহার করব না তখনই সেটি মেমোরি থেকে সরিয়ে নিব।

} // end of request_handler function

ফাংশন শেষ!

ব্রাউজারকে ওয়েবসার্ভার যখন উত্তর পাঠায় সেই উত্তরগুলোতে কি কি তথ্য থাকবে সেটি এমিট রিপ্লাই ফাংশনটি সামলায়।

void emit_reply(int conn, Reply rply)
{

ফাংশন শুরু হল।

//pthread_mutex_lock(&emitMutex2);
if(rply.code == 200)
{

ইয়াহু! পেজটি সার্ভারে পাওয় গেছে!

char *ok_code = "HTTP/1.1 200 OK\r\n";
write(conn, ok_code, strlen(ok_code));

সুখবরের একটি কোড আছে। সেটি সেট করি।

char *date;
date = (char *)malloc(100);
strcpy(date, "Date: ");
strcat(date, rply.date);
strcat(date, "\r\n");
write(conn, date, strlen(date));

তারিখ সেট করি।

char *server;
server = (char *)malloc(100);
strcpy(server, "Server: ");
strcat(server, rply.server);
strcat(server, "\r\n");
write(conn, server, strlen(server));

কে উত্তর পাঠাচ্ছে সেটি জানাই।

char *last_modified;
last_modified = (char *)malloc(100);
strcpy(last_modified, "Last-Modified: ");
strcat(last_modified, rply.last_modified);
strcat(last_modified, "\r\n");
write(conn, last_modified, strlen(last_modified));

ওয়েবপেজটি সর্বশেষ কবে আপডেট করা হয়েছে তা জানাই।

char *content_length;
content_length = (char *)malloc(100);
strcpy(content_length, "Content-Length: ");
int decpnt, sign;
char *p;
p = (char *)malloc(20);
p = ecvt(rply.content_length, 15, &decpnt, &sign);
//printf("\nConversion-- %s %d %d", p, decpnt, sign);
 
strncat(content_length, p, decpnt);
strcat(content_length, "\r\n");
write(conn, content_length, strlen(content_length));

ওয়েবপেজ কত বাইট সেটি জানাই।

char *content_type;
content_type = (char *)malloc(100);
strcpy(content_type, "Content-Type: ");
strcat(content_type, rply.content_type);
strcat(content_type, "\r\n");
write(conn, content_type, strlen(content_type));

এটি ছবি, ভিডিও না শুধু লেখা সেই তথ্যটি জানাই।

write(conn, "\r\n", 2);
 
int b;
char c;
FILE *fp;
fp = (FILE *) malloc(sizeof(FILE));
fp = fopen(rply.file_path, "rb");
while(!feof(fp))
{
   c = getc(fp);
   if(!feof(fp))
   {
      //printf("%c", c);
      write(conn, &c, 1);
   }
}

এবার পেজটি পাঠাই।

//pthread_mutex_unlock(&emitMutex2);
return;
}

ফাংশন শেষ!

else if(rply.code == 400)
{
   char *ok_code = "HTTP/1.1 400 Bad Request\r\n";
   write(conn, ok_code, strlen(ok_code));
   
   char *date;
   date = (char *)malloc(100);
   strcpy(date, "Date: ");
   strcat(date, rply.date);
   strcat(date, "\r\n");
   write(conn, date, strlen(date));
   char *server;
   server = (char *)malloc(100);
   strcpy(server, "Server: ");
   strcat(server, rply.server);
   strcat(server, "\r\n");
   write(conn, server, strlen(server));
   write(conn, "\r\n", 2);
   
   char *error_400;
   error_400 = (char *)malloc(300);
   strcpy(error_400, "<html><head><title>Error No: 400. Bad Request.</title></head><body><h2>The server cannot parse the request.</h2><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><hr>For further info mail to shehab_sust@yahoo.com.</body><html>");
   write(conn, error_400, strlen(error_400));
}

যদি পেজটি পাওয়া না যায় তাহলে দু:সংবাদ জানিয়ে দেই।

else if(rply.code == 501)
{
   char *ok_code = "HTTP/1.1 501 Method Not Implemented\r\n";
   write(conn, ok_code, strlen(ok_code));

   char *date;
   date = (char *)malloc(100);
   strcpy(date, "Date: ");
   strcat(date, rply.date);
   strcat(date, "\r\n");
   write(conn, date, strlen(date));

   char *server;
   server = (char *)malloc(100);
   strcpy(server, "Server: ");
   strcat(server, rply.server);
   strcat(server, "\r\n");
   write(conn, server, strlen(server));
   write(conn, "\r\n", 2);

   char *error_501;
   error_501 = (char *)malloc(300);
   strcpy(error_501, "<html><head><title>Error No: 501. Method Not Implemented.</title></head><body><h2>The server only resolves the GET method.</h2><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><hr>For further info mail to shehab_sust@yahoo.com.</body><html>");
   write(conn, error_501, strlen(error_501));
}

এর মানে হল রিকোয়েস্টে কোন সমস্যা নেই কিন্তু যে মেথডে চাওয়া হয়েছে সেটির সাপোর্ট আমি এখনও দেই নি। দোষ আমারই।

else if(rply.code == 404)
{
   char *ok_code = "HTTP/1.1 404 File Not Found\r\n";
   write(conn, ok_code, strlen(ok_code));
   
   char *date;
   date = (char *)malloc(100);
   strcpy(date, "Date: ");
   strcat(date, rply.date);
   strcat(date, "\r\n");
   write(conn, date, strlen(date));

   char *server;
   server = (char *)malloc(100);
   strcpy(server, "Server: ");
   strcat(server, rply.server);
   strcat(server, "\r\n");
   write(conn, server, strlen(server));
   
   write(conn, "\r\n", 2);

   char *error_404;
   error_404 = (char *)malloc(300);
   strcpy(error_404, "<html><head><title>Error No: 404. File Not Found.</title></head><body><h2>The server could not found the requested url.</h2><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><hr>For further info mail to shehab_sust@yahoo.com.</body><html>");
   write(conn, error_404, strlen(error_404));
}

এর মানে হল ওয়েবসার্ভারে অনুরোধকৃত পেজের কোন অস্তিত্ত্বই নেই।

else if(rply.code == 403)
{
   char *ok_code = "HTTP/1.1 403 Forbidden\r\n";
   write(conn, ok_code, strlen(ok_code));

   char *date;
   date = (char *)malloc(100);
   strcpy(date, "Date: ");
   strcat(date, rply.date);
   strcat(date, "\r\n");
   write(conn, date, strlen(date));

   char *server;
   server = (char *)malloc(100);
   strcpy(server, "Server: ");
   strcat(server, rply.server);
   strcat(server, "\r\n");
   write(conn, server, strlen(server));

   write(conn, "\r\n", 2);

   char *error_403;
   error_403 = (char *)malloc(300);
   strcpy(error_403, "<html><head><title>Error No: 403. Forbidden.</title></head><body><h2>You are not authorized to access this url.</h2><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><hr>For further info mail to shehab_sust@yahoo.com.</body><html>");
 
   write(conn, error_403, strlen(error_403));
}

এর মানে হল পেজটি আছে কিন্তু দেখানো যাবেনা।

} //end of emit_reply

ফাংশন শেষ!

ওয়েবসার্ভারে যে শুধুমাত্র পেজের রিকোয়েস্টই আসে তা নয়। এটি একটি ছবির রিকোয়েস্ট হতে পারে, ভিডিওর রিকোয়েস্ট হতে পারে বা অন্যকিছুও হতে পারে। রিকোয়েস্ট থেকে সেটি বুঝে নিয়ে আবার রিপ্লাইতে বলে দিতে হয় কি ধরনের ডেটা পাঠানো হচ্ছে। গেটমাইমটাইপ নামে একটি ফাংশন এটি সামলায়।

char *getMimeType(char *str)
{
   printf("\nentered mime type");
   int i;
   //defined here the file extension
   char *fileExt[MAX];
   fileExt[0] = "html";
   fileExt[1] = "htm";
   fileExt[2] = "txt";
   fileExt[3] = "gif";
   fileExt[4] = "jpg";
   fileExt[5] = "qt";

   //defined here the mime type
   char *mType[MAX];
   mType[0] = "text/html";
   mType[1] = "text/html";
   mType[2] = "text/plain";
   mType[3] = "image/gif";
   mType[4] = "image/jpeg";
   mType[5] = "video/quicktime";

   for(i = 0; i < 6; i++)
   {
      if(strcmp(str, fileExt[i]) == 0)
      {
         printf("\nmatched");
         return mType[i];
      }
   } //end of for loop
   printf("\nreturning ERROR");
   char *er = "ERROR";
   return er;
} //end of getMimetype

ফাংশনটির আইডিয়া খুব সহজ। রিকোয়েস্ট থেকে মাইমটাইপ পড়ে সে অনুযায়ী রিপ্লাইয়ের মাইমটাইপ ঠিক করে দিবে।

রিপ্লাই হিসেবে যে বাইটগুলো পাঠানো হয় সেগুলো গুছানোর জন্য প্রিপেয়ার রিপ্লাই নামে একটি ফাংশন ব্যবহার করা হয়।

Reply prepare_reply(int code, Request rq)
{

ফাংশন শুরু হল।

// extracting the file extension
char *drive, *direc, *fname, *ext;

drive = (char *) malloc (3);
direc = (char *) malloc (66);
fname = (char *) malloc (9);
ext = (char *) malloc (5);

Reply rpl;

শুরুতে মেমোরীতে কিছু জায়গা গুছিয়ে নেই।

if(code == 200)
{

এর মানে হল আমরা ওয়েবসাইট ভিজিটরকে জানাতে যাচ্ছে যে পেজটি সার্ভারে পাওয়া গেছে।

rpl.code = 200;
 
time_t lt;
lt = time(NULL);
strcpy(rpl.date, ctime(&lt));
rpl.date[strlen(rpl.date) - 1] = '\0';
 
strcpy(rpl.server, "TinyThreadedServer/0.1a");

কিছু খুচরো তথ্য গুছিয়ে নেই।

char dir[100];
getcwd(dir, 100);
//printf("\ncurrent dir is %s", dir);
//printf("\nfile path is %s", rq.filePath);
strcat(dir, "/");
strcat(dir, rq.filePath);
//printf("\nabsolute file path is %s", dir);
char *path, *p;
path = (char *) malloc (80);
p = (char *) malloc (80);
path = strtok(dir, "/");
strcpy(p, "/");
strcat(p, path);
do{
   path = strtok('\0', "/");
   if(path)
   {
      strcpy(ext, path);
      strcat(p, "/");
      strcat(p, path);
   }
} while(path);
//printf("\nthe c++ file path %s", p);

হার্ডডিস্কে কোথায় ফাইলটি আছে খুঁজে নেই।

char *e;
e = (char *)malloc(10);
e = strtok(ext, ".");
e = strtok('\0', ".");
//printf("\nfile extension is %s", e);

ফাইলের এক্সটেনশনটি জেনে নেই।

FILE *fp;
fp = (FILE *) malloc(sizeof(FILE));
if((fp = fopen(p, "r")) == NULL)
{
   printf("\nFILE NOT FOUND.\nERROR CODE 404");
   rpl.code = 404;
   return rpl;
}

ফাইলটি পড়া যায় কিনা দেখি।

struct stat buff;
stat(p, &buff);
//printf("\nSize: %ld\ntime of last modification: %s", buff.st_size, ctime(&buff.st_mtime));

strcpy(rpl.last_modified, ctime(&buff.st_mtime));
rpl.last_modified[strlen(rpl.last_modified) - 1] = '\0';

ফাইলটি সর্বশেষ কবে আপডেট করা হয়েছে সেই তথ্যটি টুকে নেই।

rpl.content_length = buff.st_size;

ফাইলের সাইজ কত সেই তথ্যটি নেই।

if(strcmp(getMimeType(e), "ERROR") == 0)
{
   rpl.code = 403;
   fclose(fp);
   return rpl;
}

ফাইলটি পড়ার পারমিশন আছে কিনা দেখি।

   strcpy(rpl.content_type, getMimeType(e));
   strcpy(rpl.file_path, p);
   fclose(fp);
}

আরো কিছু তথ্য নেই।

else if (code == 400)
{
   rpl.code = 400;

   time_t lt;
   lt = time(NULL);
   strcpy(rpl.date, ctime(&lt));
   rpl.date[strlen(rpl.date) - 1] = '\0';

   strcpy(rpl.server, "TinyThreadedServer/0.1a");
}

এর মানে হল ফাইলটি পাওয়া যায় নি।

else if (code == 501)
{
   rpl.code = 501;

   time_t lt;
   lt = time(NULL);
   strcpy(rpl.date, ctime(&lt));
   rpl.date[strlen(rpl.date) - 1] = '\0';
   
   strcpy(rpl.server, "TinyThreadedServer/0.1a");
}

এর মানে হল ফাইলটি আছে কিন্তু পড়ার পারমিশন নেই।

   return rpl;
} //end of prepare_reply

ফাংশন শেষ।

কোন ব্রাউজার যখন রিকোয়েস্ট পাঠায় তখন সেখানে অনেক ধরণের তথ্য থাকে। সেগুলো ধরে ধরে বুঝার জন্য পারস রিকোয়েস্ট ফাংশনটি ব্যবহার করা হয়।

Request parse_request(char *rbuff)
{
   char *fileName;
   char *hostName;
   int j, k, l, m, n;
   Request r;

ফাংশন শুরু হল।

fileName = (char *) malloc (100);
hostName = (char *) malloc (100);

মেমোরীতে একটু জায়গা নেই।

for(j = 5, k = 0; ;j++, k++)
{
   if(rbuff[j] == ' ') break;
   fileName[k] = rbuff[j];
} //end of for loop
fileName[k]= '\0';
//printf("\nThe valid file path is %s", fileName);
strcpy(r.filePath, fileName);

কোন ওয়েবপেজ দেখতে চায় সেটি জেনে নেই।

//finding the host
char *p;
p = strstr(rbuff, "Host: ");

for(l = 0; l < 6; l++)
{
   p++;
} //end of for loop

for(m = 0, n = 0; ; m++, n++)
{
   if(*p == '\r' || *p == '\n') break;
   hostName[n] = *p;
   p++;
} //end of for loop
hostName[n]= '\0';

fflush(stdout);
strcpy(r.hostName, hostName);

রিকোয়েস্টটি কোন কম্পিউটার থেকে এসেছে জেনে নেই।

   return r;
} // end of parse_request

ফাংশন শেষ।

একটি ওয়েব পেজ দেখার রিকোয়েস্টে অনেক ধরণের মেথড থাকতে পারে, যেমন, গেট, পুট ইত্যাদি। আমার এই সার্ভার শুধু মাত্র গেট সাপোর্ট করে। এই ব্যাপারগুলো সামলানোর জন্য ফাইন্ড মেথড ফাংশনটি ব্যবহার করা হয়।

int find_method (char *req)
{
   pthread_mutex_lock(&srvrMutex2);
   //printf("\nin the find_method function\n%s\nthe size of the request is: %d", req, strlen(req));

   char *method_list[6];
   method_list[0] = (char *) malloc (10);
   strcpy(method_list[0], "PUT");
   method_list[1] = (char *) malloc (10);
   strcpy(method_list[1], "HEAD");
   method_list[2] = (char *) malloc (10);
   strcpy(method_list[2], "POST");
   method_list[3] = (char *) malloc (10);
   strcpy(method_list[3], "DELETE");
   method_list[4] = (char *) malloc (10);
   strcpy(method_list[4], "TRACE");
   method_list[5] = (char *) malloc (10);
   strcpy(method_list[5], "CONNECT");
 
   int i, j = 0;
   char *r;
   r = (char *) malloc (10);
   for(i = 0; i < strlen(req); i++)
   {
      if(req[i] == ' ') break;
      r[i] = req[i];
   } //end of for loop
   r[i] = '\0';
   //printf("\nExtracted method is %s", r);

   if(strcmp(r, "GET") == 0)
   {
      //printf("\nit's a GET method !!!");
      pthread_mutex_unlock(&srvrMutex2);
      return 0;
   }
 
   for(i = 0; i < 7; i++)
   {
      if(strcmp(r, method_list[i]) == 0)
      {
         printf("\n%s matched with %s", r, method_list[i]);
         j = 1;
         break;
      }
   } //end of for loop

   if(j == 1)
   {
      pthread_mutex_unlock(&srvrMutex2);
      return 1;
   }
   else
   {
      pthread_mutex_unlock(&srvrMutex2);
      return -1;
   }
} // end of find_method

গেট মেথড হলে আমি আগাবো না হলে স্যরি বলে দিব।

কোড এখানেই শেষ! পড়ার জন্য ধন্যবাদ! এখন একটু মাথা খাটিয়ে বের করা আমার ওয়েব সার্ভারের সোর্স কোডের ফাইলের নাম allizom রেখেছি কেন?