মনে করুন আমাদের কাছে দুটি পিয়ার নোড রয়েছে: প্রথম নোড দ্বিতীয়টির সাথে সংযোগের অনুরোধ পাঠাতে পারে, তবে দ্বিতীয়টি প্রথমটিতে একটি সংযোগের অনুরোধটি প্রেরণ করতে পারে। কীভাবে দুটি নোডের মধ্যে ডাবল সংযোগ এড়ানো যায়? এই সমস্যাটি সমাধান করার জন্য, ইনবাউন্ড বা আউটবাউন্ড টিসিপি সংযোগ তৈরির জন্য সম্পাদিত ক্রিয়াকলাপগুলি যথাযথ করা যথেষ্ট।
এর অর্থ হ'ল প্রতিটি নোড আগত সংযোগ এবং বহির্গামী সংযোগগুলির জন্য প্রতিটি নতুন সংযোগ তৈরির ক্রিয়াকলাপটি ক্রমানুসারে প্রক্রিয়া করা উচিত। এইভাবে, সংযুক্ত নোডগুলির একটি তালিকা বজায় রাখা, কোনও নোড থেকে নতুন আগত সংযোগ গ্রহণ করার আগে বা নোডের সাথে সংযোগের অনুরোধ প্রেরণের আগে, এই নোডটি তালিকায় ইতিমধ্যে উপস্থিত কিনা তা খতিয়ে দেখতে যথেষ্ট হবে।
সংযোগ তৈরির ক্রম ক্রিয়াকলাপ করার জন্য , সংযুক্ত নোডগুলির তালিকায় একটি লক সম্পাদন করা যথেষ্ট : বাস্তবে, প্রতিটি নতুন সংযোগের জন্য, এই তালিকায় নতুন সংযুক্ত নোডের সনাক্তকারী যুক্ত করা হয়। তবে আমি ভাবছি যে এই পদ্ধতির কারণে বিতরণকৃত অচলাবস্থা সৃষ্টি হতে পারে :
- প্রথম নোড দ্বিতীয়টিতে সংযোগের অনুরোধ পাঠাতে পারে;
- দ্বিতীয় নোড প্রথমটির সাথে সংযোগের অনুরোধ পাঠাতে পারে;
- ধরে নিলাম যে দুটি সংযোগের অনুরোধগুলি তাত্পর্যপূর্ণ নয়, উভয় নোডই আগত সংযোগের যে কোনও অনুরোধ লক করে lock
আমি কীভাবে এই সমস্যার সমাধান করতে পারি?
আপডেট: তবে, এখনও প্রত্যেকবার নতুন (আগত বা বহির্গামী) সংযোগ তৈরি হওয়ার পরে আমাকে তালিকায় লক করতে হবে, যেহেতু অন্যান্য থ্রেডগুলি এই তালিকায় অ্যাক্সেস করতে পারে, তবে অচলাবস্থার সমস্যাটি এখনও থেকেই যাবে।
আপডেট 2: আপনার পরামর্শের ভিত্তিতে আমি লগইন অনুরোধের পারস্পরিক গ্রহণযোগ্যতা রোধ করতে একটি অ্যালগরিদম লিখেছিলাম। যেহেতু প্রতিটি নোড পিয়ার, তাই এটিতে নতুন সংযোগের অনুরোধগুলি প্রেরণের ক্লায়েন্ট রুটিন এবং ইনকামিং সংযোগগুলি গ্রহণ করার জন্য একটি সার্ভার রুটিন থাকতে পারে।
ClientSideLoginRoutine() {
for each (address in cache) {
lock (neighbors_table) {
if (neighbors_table.contains(address)) {
// there is already a neighbor with the same address
continue;
}
neighbors_table.add(address, status: CONNECTING);
} // end lock
// ...
// The node tries to establish a TCP connection with the remote address
// and perform the login procedure by sending its listening address (IP and port).
boolean login_result = // ...
// ...
if (login_result)
lock (neighbors_table)
neighbors_table.add(address, status: CONNECTED);
} // end for
}
ServerSideLoginRoutine(remoteListeningAddress) {
// ...
// initialization of data structures needed for communication (queues, etc)
// ...
lock(neighbors_table) {
if(neighbors_table.contains(remoteAddress) && its status is CONNECTING) {
// In this case, the client-side on the same node has already
// initiated the procedure of logging in to the remote node.
if (myListeningAddress < remoteListeningAddress) {
refusesLogin();
return;
}
}
neighbors_table.add(remoteListeningAddress, status: CONNECTED);
} // end lock
}
উদাহরণ: আইপি: নোডের পোর্টটি হ'ল এ: 7001 - আইপি: নোড বি এর বন্দরটি বি: 8001।
মনে করুন যে নোড এ নোড বি: 8001 এ একটি লগইন অনুরোধ প্রেরণ করেছে। এই ক্ষেত্রে, নোড এ তার নিজস্ব শ্রবণ ঠিকানা (এ: 7001) প্রেরণ করে লগইন রুটিনকে কল করে। ফলস্বরূপ, নোড এ এর প্রতিবেশী_সারণীতে রিমোট নোডের ঠিকানা রয়েছে (বি: 8001): এই ঠিকানাটি সংযোগের স্থিতির সাথে সম্পর্কিত। নোড এ নোড বি লগইনের অনুরোধ গ্রহণ বা অস্বীকার করার অপেক্ষায় রয়েছে।
এদিকে নোড বি নোড এ (এ: 1০০১) এর ঠিকানায় সংযোগের অনুরোধটি প্রেরণ করতে পারে, নোড এ নোড বিয়ের অনুরোধটি প্রক্রিয়াকরণ করতে পারে, সুতরাং নোড বি এর প্রতিবেশী_সমাথায় রিমোটের ঠিকানা রয়েছে নোড (এ: 7001): এই ঠিকানাটি সংযোগের রাজ্যের সাথে সম্পর্কিত। নোড বি নোডের জন্য অপেক্ষা করছে একটি লগইনের অনুরোধ গ্রহণ বা অস্বীকার করবে।
নোড এ এর সার্ভার সাইডটি যদি বি: 8001 এর অনুরোধটি প্রত্যাখ্যান করে তবে আমার অবশ্যই নিশ্চিত নোড বি এর সার্ভার দিকটি এ: 7001 থেকে অনুরোধটি গ্রহণ করবে। একইভাবে, নোড বি এর সার্ভার সাইডটি যদি এ: 7001 এর অনুরোধটি প্রত্যাখ্যান করে তবে আমার অবশ্যই নিশ্চিত নোড এ এর সার্ভার সাইডটি বি: 8001 থেকে অনুরোধটি গ্রহণ করবে।
মতে "ছোট ঠিকানা" নিয়ম এই ক্ষেত্রে নোড এ, নোড বি দ্বারা লগইন অনুরোধে প্রত্যাখ্যান যখন নোড বি নোড A. থেকে অনুরোধটি স্বীকার করবে
তুমি এটা সম্পর্কে কী ভাব?