টিসিপি: দুটি আলাদা সকেট কী কোনও বন্দর ভাগ করে নিতে পারে?


124

এটি একটি খুব প্রাথমিক প্রশ্ন হতে পারে তবে এটি আমাকে বিভ্রান্ত করে।

দুটি পৃথক সংযুক্ত সকেট একটি বন্দর ভাগ করতে পারে? আমি একটি অ্যাপ্লিকেশন সার্ভারটি লিখছি যা 100k এর বেশি সমবর্তী সংযোগগুলি পরিচালনা করতে সক্ষম হওয়া উচিত এবং আমরা জানি যে কোনও সিস্টেমে উপলব্ধ পোর্টগুলির সংখ্যা 60 কে (16 বিট) এর কাছাকাছি। একটি সংযুক্ত সকেট একটি নতুন (উত্সর্গীকৃত) বন্দরে বরাদ্দ করা হয়েছে, সুতরাং এর অর্থ হল একাধিক সকেট একই পোর্টটি ভাগ না করতে পারলে সমবায় সংযোগের সংখ্যা বন্দরগুলির সংখ্যা দ্বারা সীমাবদ্ধ। তাই প্রশ্ন।

অগ্রিম সহায়তার জন্য ধন্যবাদ!

উত্তর:


175

একটি সার্ভার সকেট একটি একক বন্দরে শোনে। সেই সার্ভারে সমস্ত প্রতিষ্ঠিত ক্লায়েন্ট সংযোগগুলি সংযোগের সার্ভারের পাশের একই শ্রবণ পোর্টের সাথে যুক্ত। একটি প্রতিষ্ঠিত সংযোগটি ক্লায়েন্ট-সাইড এবং সার্ভার-সাইড আইপি / পোর্ট জোড়াগুলির সংমিশ্রণ দ্বারা স্বতন্ত্রভাবে চিহ্নিত করা যায়। একই সার্ভারে একাধিক সংযোগ যতক্ষণ না তারা বিভিন্ন ক্লায়েন্ট-সাইড আইপি / পোর্ট জোড়গুলির সাথে যুক্ত থাকে ততক্ষণ একই সার্ভার-সাইড আইপি / পোর্ট জুড়িটি ভাগ করতে পারে এবং সার্ভার যতটা ক্লায়েন্ট হ্যান্ডেল করতে সক্ষম হবে যতগুলি উপলভ্য সিস্টেম সংস্থানগুলি এটির অনুমতি দেয় প্রতি.

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


2
উত্তরের জন্য ধন্যবাদ, রেমি! আপনার উত্তরটি হ'ল আমি আগ্রহী was ;)
কেজে

2
@ রেমি সংযোগগুলি কেবল উত্স / গন্তব্য পোর্ট / আইপি দ্বারা নয়, প্রোটোকল (টিসিপি, ইউডিপি ইত্যাদি) দ্বারাও বৈষম্যমূলক হয়, যদি আমার ভুল না হয়।
ওন্দ্রেজ পিটারকা

1
@ ওন্দ্রপেটেরকা: হ্যাঁ, তবে সমস্ত প্ল্যাটফর্মই এতে সীমাবদ্ধ নয়। উদাহরণস্বরূপ, উইন্ডোজ সুখে একই আইপিভি 4 এবং আইপিভি 6 সার্ভার সকেটগুলিকে একই লোকাল আইপি শুনতে দেয়: হুপের মাধ্যমে ঝাঁপ না দিয়ে পোর্ট, তবে * নিক্স সিস্টেমগুলি (লিনাক্স এবং অ্যান্ড্রয়েড সহ) তা দেয় না।
রেমি লিবাউ

6
@ ব্যবহারকারী 2268997: আপনি একাধিক সার্ভারের সাথে সংযোগ করতে একটি একক সকেট ব্যবহার করতে পারবেন না। প্রতিটি সংযোগের জন্য আপনাকে অবশ্যই আলাদা সকেট তৈরি করতে হবে।
রেমি লেবেউ

3
@ ফার্নান্দোগোঞ্জালেজ সানচেজ: একক ক্লায়েন্টের একাধিক টিসিপি সকেট একই স্থানীয় আইপি / পোর্ট জোড়ায় আবদ্ধ থাকতে পারে যতক্ষণ না তারা বিভিন্ন দূরবর্তী আইপি / পোর্ট জোড়ায় সংযুক্ত থাকে। এটি উইন্ডোজের সাথে নির্দিষ্ট নয়, এটি টিসিপি সাধারণভাবে কীভাবে কাজ করে তার একটি অংশ।
রেমি লিবিউ

182

টিসিপি / এইচটিটিপি পোর্টে শুনছেন: কীভাবে অনেক ব্যবহারকারী একই বন্দরে ভাগ করতে পারেন

সুতরাং, যখন কোনও সার্ভার টিসিপি পোর্টে আগত সংযোগগুলির জন্য শোনার পরে কী ঘটে? উদাহরণস্বরূপ, আসুন আমরা 80 পোর্টে আপনার একটি ওয়েব-সার্ভার রয়েছে বলে ধরা যাক আপনার কম্পিউটারের 24.14.181.229 এর সার্বজনীন আইপি ঠিকানা রয়েছে এবং যে ব্যক্তি আপনার সাথে সংযোগ স্থাপনের চেষ্টা করছে তার IP ঠিকানা 10.1.2.3 রয়েছে। এই ব্যক্তিটি 24.14.181.229:80 এ টিসিপি সকেট খোলার মাধ্যমে আপনার সাথে সংযোগ করতে পারে। যথেষ্ট সহজ।

স্বজ্ঞাতভাবে (এবং ভুলভাবে), বেশিরভাগ লোকেরা ধরে নেন যে এটি দেখতে এরকম কিছু দেখাচ্ছে:

    Local Computer    | Remote Computer
    --------------------------------
    <local_ip>:80     | <foreign_ip>:80

    ^^ not actually what happens, but this is the conceptual model a lot of people have in mind.

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

তিনটি বিষয় অবশ্যই বুঝতে হবে:

1.) একটি সার্ভারে, একটি প্রক্রিয়া একটি বন্দরে শুনছে । এটি সংযোগ পাওয়ার পরে এটি অন্য থ্রেডে ছেড়ে দেয়। যোগাযোগ শ্রবণ বন্দরে কখনই হোগ করে না।

২) সংযোগগুলি নিম্নলিখিত 5 টি টিপল দ্বারা ওএস দ্বারা স্বতন্ত্রভাবে সনাক্ত করা যায়: (লোকাল-আইপি, লোকাল-পোর্ট, রিমোট-আইপি, রিমোট-পোর্ট, প্রোটোকল) যদি টিপলটিতে কোনও উপাদান আলাদা হয়, তবে এটি সম্পূর্ণ স্বাধীন সংযোগ।

৩) যখন কোনও ক্লায়েন্ট কোনও সার্ভারের সাথে সংযুক্ত হয়, তখন এটি একটি এলোমেলো, অব্যবহৃত উচ্চ-অর্ডার উত্স পোর্টটি চয়ন করে । এইভাবে, একক ক্লায়েন্টের একই গন্তব্য পোর্টের জন্য সার্ভারের সাথে ~ 64k পর্যন্ত সংযোগ থাকতে পারে।

সুতরাং, যখন কোনও ক্লায়েন্ট কোনও সার্ভারের সাথে সংযোগ স্থাপন করে তখন এটি তৈরি হয়:

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

আসলে কী ঘটে তা দেখছি

প্রথমে এই কম্পিউটারে কী ঘটছে তা দেখতে নেটট্যাট ব্যবহার করা যাক। আমরা 80 এর পরিবর্তে 500 পোর্ট ব্যবহার করব (কারণ একটি সাধারণ বন্দর হওয়ায় 80 পোর্টে পুরো গোছা ঘটনা ঘটছে, তবে কার্যত এটি কোনও তাত্পর্য রাখে না)।

    netstat -atnp | grep -i ":500 "

প্রত্যাশিত হিসাবে, আউটপুট ফাঁকা। এখন একটি ওয়েব সার্ভার শুরু করা যাক:

    sudo python3 -m http.server 500

এখন, আবার নেটস্যাট চালানোর আউটপুট এখানে:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

সুতরাং এখন একটি প্রক্রিয়া রয়েছে যা সক্রিয়ভাবে শুনছে (স্টেট: LISTEN) পোর্ট 500 এ। স্থানীয় ঠিকানাটি 0.0.0.0, যা "সমস্ত আইপি ঠিকানার জন্য শোনার" কোড। একটি সহজ ভুলটি কেবল 127.0.0.1 বন্দরটিতে শুনতে হবে, যা কেবলমাত্র বর্তমান কম্পিউটার থেকে সংযোগ গ্রহণ করবে। সুতরাং এটি কোনও সংযোগ নয়, এর অর্থ হ'ল কোনও প্রক্রিয়া আইপি-তে পোর্ট করার জন্য () বাঁধতে অনুরোধ করেছিল এবং সেই প্রক্রিয়াটি সেই বন্দরের সাথে সমস্ত সংযোগ পরিচালনা করার জন্য দায়ী। এই সীমাবদ্ধতার প্রতি ইঙ্গিত দেয় যে কোনও বন্দরে কম্পিউটারে শোনার জন্য কেবল একটি প্রক্রিয়া থাকতে পারে (মাল্টিপ্লেক্সিং ব্যবহার করে এটি ঘুরে দেখার উপায় রয়েছে তবে এটি আরও জটিল বিষয়)। যদি কোনও ওয়েব-সার্ভার ৮০ পোর্টে শুনছে তবে এটি অন্য ওয়েব-সার্ভারের সাথে পোর্টটি ভাগ করতে পারে না।

এখন, আসুন একটি ব্যবহারকারীকে আমাদের মেশিনে সংযুক্ত করুন:

    quicknet -m tcp -t localhost:500 -p Test payload.

এটি একটি সাধারণ স্ক্রিপ্ট ( https://github.com/grokit/quickweb ) যা একটি টিসিপি সকেট খোলে, পে-লোড প্রেরণ করে ("এই ক্ষেত্রে টেস্ট পেলোড" "), কয়েক সেকেন্ড অপেক্ষা করে এবং সংযোগ বিচ্ছিন্ন হয়ে যায়। এটি হওয়ার সময় আবার নেটস্যাট করা নিম্নলিখিত বিষয়গুলি প্রদর্শন করে:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -

আপনি যদি অন্য ক্লায়েন্টের সাথে সংযোগ স্থাপন করেন এবং আবার নেটস্যাট করেন, আপনি নিম্নলিখিতটি দেখতে পাবেন:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -

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


11
এটি আমার পক্ষে সর্বকালের সেরা উত্তর S
চাকরী

1
@ N0thing "এইভাবে, একই গন্তব্য পোর্টের জন্য একটি একক ক্লায়েন্টের সার্ভারের সাথে ~ 64k পর্যন্ত সংযোগ থাকতে পারে।" সুতরাং অনুশীলনে, যদি কোনও ক্লায়েন্ট একই সার্ভার এবং পোর্টের সাথে দু'বার বা একাধিকবার একযোগে সংযোগ না দেয়, তবে ক্লায়েন্টের কাছে ~ 64K এরও বেশি সংযোগ থাকতে পারে। এটা কি সত্যি. যদি হ্যাঁ হয় তবে এর থেকে বোঝা যায় যে ক্লায়েন্টের একক পোর্ট থেকে এটির বিভিন্ন সার্ভার প্রক্রিয়াতে সংযোগ থাকতে পারে (যেমন সকেট সংযোগটি আলাদা))। সুতরাং সব মিলিয়ে একাধিক ক্লায়েন্ট সকেটগুলি ক্লায়েন্ট মেশিনে একই বন্দরে থাকতে পারে? "রেমি রেবেউ" উত্তরে আমার মন্তব্যটি পড়ুন। ধন্যবাদ: ডি
প্রেম কেটিউ

6
@ প্রিমকিটিউ: হ্যাঁ, একাধিক ক্লায়েন্ট সকেটগুলি একই সময়ে একই স্থানীয় আইপি / পোর্ট জোড়ায় আবদ্ধ হতে পারে, যদি তারা বিভিন্ন সার্ভারের আইপি / পোর্ট জোড়ের সাথে সংযুক্ত থাকে তাই স্থানীয় + দূরবর্তী জোড়াগুলির টিউপসটি অনন্য। এবং হ্যাঁ, কোনও ক্লায়েন্টের পক্ষে মোট 64K এর বেশি সমবর্তী সংযোগ থাকা সম্ভব। একটি একক বন্দর থেকে, সার্ভারের আইপি / পোর্ট জোড়াটি অনন্য হয়ে না থাকলে এটি সম্ভাব্য সীমাহীন সংখ্যক সার্ভারের সাথে (উপলব্ধ ওএস রিসোর্স, উপলব্ধ রাউটার পোর্ট ইত্যাদি দ্বারা সীমাবদ্ধ) সংযুক্ত হতে পারে।
রেমি Lebeau

1
পুনঃটুইট করেছেন আপনাকে অনেক অনেক ধন্যবাদ: ডি
প্রেম কেটিউ

1
@ বিবস্থা সমস্ত আগত সংযোগগুলি প্রত্যাখ্যান করার সাথে সাথে ফায়ারওয়াল কীভাবে এলোমেলো বন্দরগুলি ব্যবহার করবে?
প্যাট্রিক জি

35

একটি সংযুক্ত সকেট একটি নতুন (উত্সর্গীকৃত) বন্দরে বরাদ্দ করা হয়েছে

এটি একটি সাধারণ স্বজ্ঞাত, তবে এটি ভুল। একটি সংযুক্ত সকেট একটি নতুন / উত্সর্গীকৃত বন্দরে বরাদ্দ করা হয়নি। টিসিপি স্ট্যাকের একমাত্র আসল প্রতিবন্ধকতা অবশ্যই পূরণ করতে হবে যে প্রতিটি সকেটের সংযোগের জন্য (লোকাল_এড্রেস, লোকাল_পোর্ট, রিমোট_এড্রেস, রিমোট_পোর্ট) টিউপল অবশ্যই অনন্য হতে হবে। এইভাবে পোর্টের প্রতিটি সকেট অন্য দূরবর্তী অবস্থানের সাথে সংযুক্ত থাকাকালীন সার্ভারের একই স্থানীয় পোর্টটি ব্যবহার করে অনেকগুলি টিসিপি সকেট থাকতে পারে।

"সকেট পেয়ার" অনুচ্ছেদটি এখানে দেখুন: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=sket%20pair%20tuple&pg=PA52#v=onepage&q=sket%20pair%20tuple&f=false


1
নির্ভুল উত্তরের জন্য আপনাকে ধন্যবাদ, জেরেমি!
কেজে

6
আপনি যা বলেন তা সম্পূর্ণরূপে সার্ভারের পক্ষে সত্য। তবে বিএসডি সকেটস এপিআই এর কাঠামোর অর্থ হল যে বহির্গামী ক্লায়েন্ট-সাইড পোর্টগুলি অবশ্যই অনুশীলনে অনন্য হতে হবে, কারণ bind()অপারেশন অপারেশনের আগে connect()এমনকি স্পষ্টতই।
লার্নের মারকুইস

1
@ এজেপি হাই, আমি ভেবেছিলাম bind()যে সার্ভার সাইডে কেবল আগে ব্যবহৃত হয় accept()?তাই ক্লায়েন্ট সাইডটি নির্দিষ্ট বন্দরটিকেও আবদ্ধ করবে?
GMsoF

5
@ জিএমএসএফ: bind()ক্লায়েন্টের পক্ষে আগে ব্যবহার করা যেতে পারে connect()
রেমি লেবাউ

10

তাত্ত্বিকভাবে, হ্যাঁ অনুশীলন, না। বেশিরভাগ কার্নেল (ইনক্লু। লিনাক্স) আপনাকে bind()ইতিমধ্যে বরাদ্দকৃত বন্দরে দ্বিতীয় সেকেন্ডের অনুমতি দেয় না । এটি অনুমোদিত করার জন্য এটি সত্যিই বড় প্যাচ ছিল না।

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

পোর্ট একটি শনাক্তকারী যা একটি সকেট সনাক্ত করতে সক্ষম। টিসিপি-র ক্ষেত্রে, একটি বন্দরটি একটি 16 বিট পূর্ণসংখ্যা, তবে অন্যান্য প্রোটোকলগুলিও রয়েছে (উদাহরণস্বরূপ, ইউনিক্স সকেটে, একটি "পোর্ট" মূলত একটি স্ট্রিং)।

মূল সমস্যাটি হ'ল: যদি কোনও আগত প্যাকেট উপস্থিত হয়, কার্নেলটি তার গন্তব্য পোর্ট নম্বর দ্বারা তার সকেটটি সনাক্ত করতে পারে। এটি একটি সর্বাধিক সাধারণ উপায়, তবে এটি একমাত্র সম্ভাবনা নয়:

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

যেহেতু আপনি একটি অ্যাপ্লিকেশন সার্ভারে কাজ করছেন, এটি এটি করতে সক্ষম হবে।


2
তিনি দ্বিতীয় তৈরি করার বিষয়ে জিজ্ঞাসা করেননি bind()
লার্নের মারকুইস

1
@ user207421 আপনি কি এমন কোনও ওএস দেখেছেন যেখানে শ্রোতা সকেটগুলি সেট আপ করা হয় না bind()? আমি এটি কল্পনা করতে পারি, হ্যাঁ এটি বেশ সম্ভব, তবে সত্য যে উইনসক এবং পিক্সিক এপিআই উভয়ই bind()কলটির জন্য কলটি ব্যবহার করে, এমনকি তাদের প্যারামিটারাইজেশন কার্যত একরকম । এমনকি যদি কোনও এপিআইতে এই কল না হয় তবে কোনওভাবে আপনাকে এটি বলা দরকার, আপনি কোথা থেকে আগত বাইটগুলি পড়তে চান
পিটারহ - মনিকা পুনরায় ইনস্টল করুন

1
@ user207421 অবশ্যই 100k বা ততোধিক টিসিপি সংযোগ একই পোর্টগুলির সাথে পরিচালনা করা যায়, listen()/ accept()এপিআই কলগুলি এমনভাবে সকেট তৈরি করতে পারে যাতে কার্নেল তাদের আগত পোর্টগুলির দ্বারা আলাদা করতে পারে। ওপির প্রশ্নটি তিনি যেভাবে মূলত এর জন্য জিজ্ঞাসা করেছেন সেভাবে ব্যাখ্যা করা যেতে পারে। আমি মনে করি, এটি বেশ বাস্তববাদী তবে তাঁর প্রশ্নের আক্ষরিক অর্থ এটি নয় not
পিটারহ - মনিকা পুনরায় ইনস্টল করুন

1

না। নির্দিষ্ট তাত্ক্ষণিক সময়ে একই পোর্টটি ভাগ করা সম্ভব নয়। তবে আপনি আপনার অ্যাপ্লিকেশনটিকে এমনভাবে তৈরি করতে পারেন যাতে এটি বিভিন্ন তাত্ক্ষণিকভাবে পোর্টটিকে অ্যাক্সেস করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.