কিভাবে উপলব্ধ একটি বন্দর খুঁজে পেতে?


194

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

  1. পোর্ট নম্বরের পরিসরটিতে আমার সন্ধান করা উচিত? (আমি 12345, 12346 এবং 12347 বন্দর ব্যবহার করেছি এবং এটি ভাল ছিল)।

  2. প্রদত্ত বন্দরটি অন্য একটি সফ্টওয়্যার দ্বারা দখল না করা আছে কিনা তা আমি কীভাবে জানতে পারি?

উত্তর:


277

আপনি যদি ব্যবহার করা বন্দরটি আপত্তি না করেন তবে সার্ভারসকেট কনস্ট্রাক্টরের কাছে 0 টির একটি বন্দর নির্দিষ্ট করুন এবং এটি যে কোনও ফ্রি পোর্টে শুনবে।

ServerSocket s = new ServerSocket(0);
System.out.println("listening on port: " + s.getLocalPort());

আপনি যদি কোনও নির্দিষ্ট বন্দরগুলির সেট ব্যবহার করতে চান, তবে সবচেয়ে সহজ উপায় সম্ভবত কোনও কাজ না হওয়া পর্যন্ত তাদের মাধ্যমে পুনরাবৃত্তি করা। এটার মতো কিছু:

public ServerSocket create(int[] ports) throws IOException {
    for (int port : ports) {
        try {
            return new ServerSocket(port);
        } catch (IOException ex) {
            continue; // try next port
        }
    }

    // if the program gets here, no port in the range was found
    throw new IOException("no free port found");
}

যেমন ব্যবহার করা যেতে পারে:

try {
    ServerSocket s = create(new int[] { 3843, 4584, 4843 });
    System.out.println("listening on port: " + s.getLocalPort());
} catch (IOException ex) {
    System.err.println("no available ports");
}

2
নতুন সার্ভারসকেট (0) ব্যবহার করার সময় এটি বন্ধ করার জন্য যত্ন নেওয়া উচিত! Javasourcecode.org/html/open-source/eclipse/eclipse.3.5.2/org/… এর উপর ভিত্তি করে , আমার জিস্ট.github.com/3429822
ভোরবার্গার

9
@ ফোরবার্গার, এটি সেভাবে করা জাতিগত অবস্থার ঝুঁকিপূর্ণ। সার্ভারের সকেটটি তাত্ক্ষণিকভাবে শুনতে ভাল, এটি একটি মুক্ত পোর্ট অনুসন্ধান করার জন্য এটি খোলার পরিবর্তে, এটি আবার বন্ধ করুন এবং তারপরে আবার একটি মুক্ত পোর্টে আবার খুলুন (সেই সময়ের মধ্যে এখনই অন্য কোনও কিছুর সম্ভাবনা রয়েছে যা এখন শুনছে! পোর্ট।)
গ্রাহাম এডকোম্বে

7
সম্মত, তবে এটি সঠিক ব্যবহারের ক্ষেত্রে নির্ভর করে: আমার ক্ষেত্রে এটির কিছু এপিআই-তে হস্তান্তর করার জন্য আমার একটি মুক্ত পোর্ট নম্বর বের করা দরকার (পরীক্ষার জন্য এম্বেড জেটি স্টার্টার বলুন) - সম্পর্কিত এপিআই একটি সকেট নম্বর চায় - ইতিমধ্যে একটি নয় সার্ভার সকেট খোলা হয়েছে। সুতরাং এটি নির্ভর করে।
ভোরবার্গার

4
@ ফোরবার্গার যুক্তিসঙ্গত এপিআইগুলি শোনার জন্য শূন্যকে একটি বৈধ পোর্ট নম্বর হিসাবে গ্রহণ করবে এবং তারপরে আপনাকে প্রকৃত পোর্টটি শোনা যাচ্ছে বলে জানাবে। Hovewer, অনেক যুক্তিসঙ্গত API নেই: 0 টি বন্দর পাস হওয়ার জন্য অনেক প্রোগ্রাম বিশেষত পরীক্ষা করে এবং এটি অস্বীকার করে ( ssh -D 127.0.0.0:0 ...? না!), যা সত্যিই হতাশাব্যঞ্জক। সেগুলি আমাদের কাজে লাগানোর জন্য আমাদের বেশ কয়েকটি লাইব্রেরি / প্রোগ্রাম প্যাচ করতে হয়েছিল।
জোকার_ভিডি

2
@ ফোরবার্গার কোনও বন্দর ব্যবহার করার সময় এটি বন্ধ করার জন্য যত্ন নেওয়া উচিত। new ServerSocket(0)এই ক্ষেত্রে ভিন্ন নয়। এটি সম্পর্কে আপনার প্রথম লিঙ্কে কিছুই নেই। আপনার দ্বিতীয় লিঙ্কটি নিছক দুর্বল অনুশীলন দেখায়। একবার আপনি এটি নির্মাণ করার পরে এটি ব্যবহার করা ServerSocketউচিত , এটি বন্ধ না করে একই পোর্ট নম্বরটি পুনরায় ব্যবহার করার চেষ্টা করুন। এগুলি হ'ল সময় নষ্ট করার পাশাপাশি সময়-উইন্ডো সমস্যার জন্য ঝুঁকিপূর্ণ।
লার্নের মারকুইস

57

আপনি সার্ভারসকেটের কনস্ট্রাক্টরের কাছে পোর্ট নম্বর হিসাবে 0টি পাস করলে এটি আপনার জন্য একটি বন্দর বরাদ্দ করবে।


হ্যাঁ, আমি মনে করি এটি সবচেয়ে মার্জিত সমাধান তবে কিছু কারণে এটি আমার ক্ষেত্রে কার্যকর হয় না। তবে আমার এখনও ঠিক কী ভুল তা খুঁজে বের করতে হবে।
রোমান

1
@ রোমান: কেন এটি কাজ করে না? এটি অন্তর্ভুক্ত করতে আপনার প্রশ্ন আপডেট করুন (বা লোকেরা এটিকে পরামর্শ দিবে) এবং কেন এই সমাধান আপনার জন্য ব্যর্থ হয় তা ব্যাখ্যা করুন।
হতাশিত

2
আমি ক্লায়েন্টের কাছ থেকে এই পোর্টটি কীভাবে খুঁজে পাব? ;)
এডি 22

34

জাভা ১. from থেকে শুরু করে আপনি এর মতো-সংস্থান ব্যবহার করতে পারেন:

  private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
    try (
        ServerSocket socket = new ServerSocket(0);
    ) {
      return socket.getLocalPort();

    }
  }

আপনার যদি কোনও নির্দিষ্ট ইন্টারফেসে একটি ওপেন পোর্ট খুঁজতে হয় তবে বিকল্প নির্মাণকারীদের জন্য সার্ভারসকেট ডকুমেন্টেশন চেক করুন ।

সতর্কতা: এই পদ্ধতিতে ফিরে আসা পোর্ট নম্বর ব্যবহার করে যে কোনও কোড রেসের শর্ত সাপেক্ষে - সার্ভারসকেট উদাহরণটি বন্ধ করার সাথে সাথেই একটি ভিন্ন প্রক্রিয়া / থ্রেড একই পোর্টে আবদ্ধ হতে পারে।


1
আপনি সেট না করলে এটি কাজ নাও করতে পারে SO_REUSEADDR। এবং একটি রেস শর্ত আছে, কিন্তু এটি ঠিক করা কঠিন।
ডেভিড এহরমান

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

5
@ এজেপি কখনও কখনও তৃতীয় পক্ষের কোড কোনও বন্দর গ্রহণ করে তবে সকেটটি নয় not
ক্যাপ্টেন ম্যান

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

@ user207421 আপনি পোর্টের ServerSocketপরিবর্তে একটি পরিবর্তনের জন্য তৃতীয় পক্ষের কোডটি পরিবর্তন করতে পারবেন না int
ক্যাপ্টেন ম্যান

30

উইকিপিডিয়া অনুসারে , আপনার যদি কোনও 'সুপরিচিত' বন্দর প্রয়োজন না 49152হয় 65535তবে আপনার পোর্টগুলি ব্যবহার করা উচিত ।

এএফাইক এক বন্দরের চক্রের ব্যবহার নির্ধারণের একমাত্র উপায় এটি খোলার চেষ্টা করা।


6
+1 টি। যেহেতু উইকিপিডিয়া সর্বদা নিখুঁত সত্য / তথ্যগুলির উত্স নয়, আমি ভেবেছিলাম এটি নোট করা কার্যকর হতে পারে, উইকিপিডিয়া পৃষ্ঠার উল্লেখটি "ইন্টারনেট অ্যাসাইনড নাম্বার অথোরিটি (আইএএনএ)" এর "[পরিষেবার নাম এবং পরিবহন প্রোটোকল পোর্ট নম্বর) থেকে আসে আরএফসি 6335 এর উপর ভিত্তি করে রেজিস্ট্রি ( iana.org/assignments/service-names-port-numbers/… "পৃষ্ঠা - বিভাগ 6 (এই ক্ষেত্রে" সলিড "রেফারেন্স! :))।
ওজগুরএইচ

25

আপনার যদি পরিসীমা ব্যবহারের প্রয়োজন হয় :

public int nextFreePort(int from, int to) {
    int port = randPort(from, to);
    while (true) {
        if (isLocalPortFree(port)) {
            return port;
        } else {
            port = ThreadLocalRandom.current().nextInt(from, to);
        }
    }
}

private boolean isLocalPortFree(int port) {
    try {
        new ServerSocket(port).close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

কীভাবে একটি পোর্ট চেক করবেন তা ভাবছিলাম, তারপরে এটি বন্ধ করে দিন। ধন্যবাদ সার্জিবি!
ভ্লাদ ইলি

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

পোর্ট 0 যথেষ্ট সহজ এবং ServerSocketsসাফল্যের ক্ষেত্রে দুটি তৈরি করার প্রয়োজন নেই এবং এই কোডটির টাইমিং-উইন্ডো সমস্যায় ভুগছেন না।
Lorne এর মার্কুইস

21

আপনি যদি বসন্ত ব্যবহার করেন তবে আপনি http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/util/SketUtils.html#findAv ਉਪਲੱਬਧTcpPort-- চেষ্টা করতে পারেন


যারা কৌতূহলী তাদের জন্য হুডের নীচে অন্য জবাবগুলিতে SpringUtils.findAvailableTcpPort()ঠিক একইভাবে করা হচ্ছে: একটি পোর্ট বেছে নিন তারপরে চেষ্টা করুন new ServerSocket(port)
আলেক্সি বেরেজকিন



6

এটি জাভা 6 এ আমার জন্য কাজ করে

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());

6

পরীক্ষাগুলি মাথায় রেখেই এটি করার জন্য আমি সম্প্রতি একটি ছোট গ্রন্থাগার প্রকাশ করেছি। ম্যাভেন নির্ভরতা হ'ল:

<dependency>
    <groupId>me.alexpanov</groupId>
    <artifactId>free-port-finder</artifactId>
    <version>1.0</version>
</dependency>

একবার ইনস্টল হয়ে গেলে নিখরচায় পোর্ট নম্বর পাওয়া যাবে:

int port = FreePortFinder.findFreeLocalPort();

4

যদি আপনার সার্ভারটি শুরু হয়, তবে সেই সকেটটি ব্যবহার করা হয়নি।

সম্পাদনা

কিছুটা এইরকম:

ServerSocket s = null ;

try { 
    s = new ServerSocket( 0 ); 
} catch( IOException ioe ){
   for( int i = START; i < END ; i++ ) try {
        s = new ServerSocket( i );
    } catch( IOException ioe ){}
}
// At this point if s is null we are helpless
if( s == null ) {
    throw new IOException(
       Strings.format("Unable to open server in port range(%d-%d)",START,END));
}

কে আপনাকে ভোট দিয়েছে, তা জানেন না, তবে আমি আপনাকে ভোট দিয়েছি। আপনি সার্ভারসকেট সেটআপ করার চেষ্টা করার জন্য একটি পুনরাবৃত্ত ফাংশন সেট আপ করতে পারেন এবং যদি আপনি কোনও আইওএক্সেপশন (বা যা কিছু হয়) পান তবে এটি সফলভাবে কোনও বন্দর না পাওয়া পর্যন্ত আপনি আবার চেষ্টা করবেন।
jonescb

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

2
@ রোমন ভাল, হ্যাঁ, এটি আরও ভাল হবে, এই ব্যতীত কোনও বন্দর উপলব্ধ কিনা তা জানার কোনও পদ্ধতি নেই। যদি new ServerSocket(0)আপনার বিকল্প জন্য কাজ করছে না এই। আমি মনে করি আপনার পরামর্শটি ব্যবহার করে 85% সম্ভাবনা রয়েছে।
অস্কার রাইজ

এই কোডটি ServerSocketsচিরকাল খোলা এবং ফাঁস হয়ে যায় এবং কেবল সফল যেটি শেষ তা ধরে রাখে । এটি একটি breakবিবৃতি প্রয়োজন।
লার্নের মার্কুইস

4

আপনি যদি একটি ব্যবহার করে আপনার নিজস্ব সার্ভার তৈরি করতে চান তবে আপনি ServerSocketকেবল এটির জন্য একটি বিনামূল্যে পোর্ট বেছে নিতে পারেন:

  ServerSocket serverSocket = new ServerSocket(0);
  int port = serverSocket.getLocalPort();

অন্যান্য সার্ভার বাস্তবায়নের ক্ষেত্রে একই রকম সমর্থন রয়েছে। উদাহরণস্বরূপ জেটি একটি নিখর পোর্ট বেছে নেয় যদি না আপনি স্পষ্টভাবে সেট করেন:

  Server server = new Server();
  ServerConnector connector = new ServerConnector(server);
  // don't call: connector.setPort(port);
  server.addConnector(connector);
  server.start();
  int port = connector.getLocalPort();

3

এটি আপনাকে খুব বেশি সহায়তা করতে পারে না তবে আমার (উবুন্টু) মেশিনে আমার কাছে একটি ফাইল / ইত্যাদি / পরিষেবা রয়েছে যাতে কমপক্ষে কিছু অ্যাপস দ্বারা সংরক্ষিত বন্দরগুলি দেওয়া হয়। এই অ্যাপ্লিকেশনগুলির জন্য এটি মানক বন্দর।

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

এখানে প্রায় 500 টিরও বেশি পোর্ট সংজ্ঞায়িত করা হয়েছে, প্রায় অর্ধেক ইউডিপি এবং অর্ধেক টিসিপি।

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


একটি অনুরূপ (এবং আরও সম্পূর্ণ, আইআইআরসি) তালিকা রয়েছে যা এনএমএপির অংশ হিসাবে আসে। +1
রুমেডোর

3

আপনি যদি স্প্রিং ব্যবহার করছেন তবে মাইকেল ম্যাকাইল নিকোলাভের দেওয়া উত্তরটি সবচেয়ে সহজ এবং পরিষ্কার একটি এবং আইএমওর উর্ধ্বতন করা উচিত। কেবল সুবিধার্থে উদ্দেশ্যে, আমি স্প্রিংফ্রেমওভার্ক সকেট ইউটিস ব্যবহার করে একটি ইনলাইন উদাহরণ যুক্ত করব f ফাইন্ড উপলভ্যতাটিসিপিপোর্ট () পদ্ধতি:

int randomAvailablePort = SocketUtils.findAvailableTcpPort();

এটি এতটা সহজ, কেবল একটি লাইন :)। অবশ্যই, ইউটিলস ক্লাসে আরও অনেক আকর্ষণীয় পদ্ধতি প্রস্তাব করা হয়, আমি ডক্সটিতে নজর দেওয়ার পরামর্শ দিই।


1

'সার্ভারসকেট' শ্রেণি ব্যবহার করে আমরা শনাক্ত করতে পারি যে প্রদত্ত বন্দরটি ব্যবহৃত হয়েছে বা বিনামূল্যে। সার্ভারসকেট এমন একটি কনস্ট্রাক্টর সরবরাহ করে যা একটি পূর্ণসংখ্যার (যা পোর্ট নম্বর) গ্রহণ করে এবং বন্দরে সার্ভার সকেটকে আরম্ভ করে। যদি সার্ভারসকেট কোনও আইও ব্যতিক্রম ছুড়ে ফেলে তবে আমরা ধরে নিতে পারি যে এই বন্দরটি ইতিমধ্যে ব্যবহৃত in

সমস্ত উপলব্ধ পোর্ট পেতে নিম্নলিখিত স্নিপেট ব্যবহার করা হয়।

for (int port = 1; port < 65535; port++) {
         try {
                  ServerSocket socket = new ServerSocket(port);
                  socket.close();
                  availablePorts.add(port);
         } catch (IOException e) {

         }
}

রেফারেন্স লিঙ্ক


0

যদি বন্দরটি অন্য সফ্টওয়্যার দ্বারা দখল করা হয় তবে কোডটি একটি আইওএক্সেপশন নিক্ষেপ করবে

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