सॉकेट: जावा का उपयोग करके पोर्ट उपलब्धता की खोज करें


123

मैं जावा का उपयोग करके किसी दिए गए मशीन में पोर्ट की उपलब्धता को प्रोग्रामेटिक रूप से कैसे निर्धारित कर सकता हूं?

यानी एक पोर्ट नंबर दिया गया है, यह निर्धारित करें कि यह पहले से ही इस्तेमाल किया जा रहा है या नहीं?


2
हालांकि यह प्रश्न यह जानने का है कि किसी दिए गए पोर्ट का उपयोग पहले से ही कैसे किया जाता है, तो आप यहां एक मुफ्त पोर्ट नंबर प्राप्त करने का एक तरीका खोजने की कोशिश कर रहे हैं, जो stackoverflow.com/questions/2675362/… (मेरे जिस्ट के लिंक के साथ) .github.com / 3429822 ) बेहतर कवर करता है।
vorburger

किस लिए? यदि आप सिर्फ सुनने के लिए एक खाली सॉकेट ढूंढना चाहते हैं, तो बस शून्य निर्दिष्ट करें। किसी भी स्कैनिंग तकनीक समय-खिड़की की समस्याओं के लिए उत्तरदायी है: जब आप दावा करने जाते हैं तो पोर्ट खाली हो सकता है और कब्जे में आ सकता है।
लोरेन की

जवाबों:


91

यह अपाचे ऊंट परियोजना से आने वाला कार्यान्वयन है :

/**
 * Checks to see if a specific port is available.
 *
 * @param port the port to check for availability
 */
public static boolean available(int port) {
    if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
        throw new IllegalArgumentException("Invalid start port: " + port);
    }

    ServerSocket ss = null;
    DatagramSocket ds = null;
    try {
        ss = new ServerSocket(port);
        ss.setReuseAddress(true);
        ds = new DatagramSocket(port);
        ds.setReuseAddress(true);
        return true;
    } catch (IOException e) {
    } finally {
        if (ds != null) {
            ds.close();
        }

        if (ss != null) {
            try {
                ss.close();
            } catch (IOException e) {
                /* should not be thrown */
            }
        }
    }

    return false;
}

वे यूपीडीपी और टीसीपी में पोर्ट अवेलेबल हैं या नहीं इसकी जांच करने के लिए वे डेटाग्रामसॉफ्ट की जांच कर रहे हैं।

उम्मीद है की यह मदद करेगा।


5
यदि आपके पास MINA उपलब्ध है, तो इसका एक अच्छा संस्करण उपलब्ध है .PortFinder.getNextAvailable (1024) जो आपको अगले गैर-विशेषाधिकार प्राप्त पोर्ट से मिलता है।
Alain O'Dea

9
हालांकि यह सब कुछ नहीं पकड़ता है। मुझे टीसीपी 8000 पर एक रनिंग नगनेक्स द्वारा काट दिया गया है जबकि उपरोक्त रूटीन रिपोर्ट 8000 उपलब्ध है। पता नहीं क्यों - मुझे संदेह है कि नगनेक्स कुछ डरपोक सामान करता है (यह ओएस एक्स पर है)। मेरे लिए समाधान ऊपर करना है और एक नया सॉकेट ("लोकलहोस्ट", पोर्ट) भी खोलना है, अगर हमें कोई अपवाद नहीं मिलता है, तो वापस लौटें। विचार?
आंशिक रूप से बादल छाए रहेंगे

2
Windows पर समान समस्या यह पता लगाने की कोशिश कर रही है कि क्या पेपरकट SMTP सर्वर चल रहा है। एक ऐसा समाधान जहां आप एक पोर्ट से कनेक्शन खोलते हैं, बजाय इसे बांधने की कोशिश के (जैसा कि आंशिक रूप से क्लोडिस टिप्पणी और इवान के जवाब द्वारा सुझाया गया है) अधिक विश्वसनीय काम करता है।
स्टेन

4
दिलचस्प। सॉकेट पहले से ही बंधे होने के बाद setReuseAddress () के लिए कॉल पूरी तरह से व्यर्थ है, और यह कोड के उद्देश्य के लिए भी पूरी तरह से विपरीत है।
लोर्ने

3
यह कोड टाइमिंग-विंडो समस्याओं के अधीन है। यदि उद्देश्य ServerSocketकुछ पोर्ट के लिए एक श्रवण बनाना है, तो उसे यही करना चाहिए, और वापस लौटना चाहिए ServerSocket। इसे बनाना और फिर इसे बंद करना और इसे वापस करना शून्य गारंटी प्रदान करता है कि बाद में ServerSocketउस पोर्ट का उपयोग करके बनाया जा सकता है। डिट्टो के लिए DatagramSocket
लोर्ने का मार्कीस

41

जावा 7 के लिए आप अधिक कॉम्पैक्ट कोड के लिए कोशिश-के-संसाधन का उपयोग कर सकते हैं:

private static boolean available(int port) {
    try (Socket ignored = new Socket("localhost", port)) {
        return false;
    } catch (IOException ignored) {
        return true;
    }
}

15
यह परीक्षण नहीं करता है कि क्या पोर्ट उपलब्ध है। यह परीक्षण करता है कि यह लिस्टेन राज्य में है या नहीं, क्या आईपी पता उपलब्ध नहीं है, आदि
मार्कोन का लोर्ने

1
इसके अतिरिक्त यह परीक्षण बहुत धीमा है (लगभग प्रति सेकंड एक पोर्ट)।
JMax

जब एक IOException पकड़ा जाता है तो क्या यह गलत नहीं लौटना चाहिए?
बरौदी सफवेन

@BaroudiSafwen यह पूरी तरह से इस बात पर निर्भर करता है कि वास्तव में अपवाद क्या है। के लिए ConnectException: 'connection refused', हाँ यह गलत होना चाहिए। समयबाह्य के लिए, ऐसा कुछ भी नहीं लौटाया जा सकता है, क्योंकि वास्तविक उत्तर ज्ञात नहीं है। इसलिए यह तकनीक इस उद्देश्य के लिए बेकार है।
लोर्ने

36

ऐसा प्रतीत होता है कि जावा 7 के रूप में, डेविड सांतामारिया का जवाब मज़बूती से काम नहीं करता है। ऐसा लगता है कि आप अभी भी कनेक्शन का परीक्षण करने के लिए मज़बूती से सॉकेट का उपयोग कर सकते हैं।

private static boolean available(int port) {
    System.out.println("--------------Testing port " + port);
    Socket s = null;
    try {
        s = new Socket("localhost", port);

        // If the code makes it this far without an exception it means
        // something is using the port and has responded.
        System.out.println("--------------Port " + port + " is not available");
        return false;
    } catch (IOException e) {
        System.out.println("--------------Port " + port + " is available");
        return true;
    } finally {
        if( s != null){
            try {
                s.close();
            } catch (IOException e) {
                throw new RuntimeException("You should handle this error." , e);
            }
        }
    }
}

मैं जांचना चाहता हूं कि क्या प्रॉक्सी सर्वर उसकी ओर से कॉल करने के लिए उपलब्ध है।
देजेल

1
@ डेविडसांतमारिया के जवाब ने कभी काम नहीं किया। जावा 7. के साथ करने के लिए कुछ भी नहीं है
लोर्न

35

यदि आप प्रदर्शन से बहुत चिंतित नहीं हैं, तो आप हमेशा सर्वरसेट क्लास का उपयोग करके पोर्ट पर सुनने की कोशिश कर सकते हैं । यदि यह एक अपवाद फेंकता है तो इसका उपयोग किया जा रहा है।

public static boolean isAvailable(int portNr) {
  boolean portFree;
  try (var ignored = new ServerSocket(portNr)) {
      portFree = true;
  } catch (IOException e) {
      portFree = false;
  }
  return portFree;
}

संपादित करें: यदि आप सभी करने की कोशिश कर रहे हैं, तो एक मुफ्त पोर्ट का चयन करें, फिर new ServerSocket(0)आपके लिए एक मिल जाएगा।


सफाई के लिए अंत में (कोशिश {...} पकड़ {...} अंत में {! अगर (सॉकेट = नल) socket.close ();} का उपयोग करें
होसाम अली

आप "portTaken = (सॉकेट == null) भी सेट कर सकते हैं;" अंत में पकड़ में करने के बजाय।
होसम ऐली

1
मुझे ऐसा नहीं लगा कि मैं लेखक के सवाल के दायरे में नहीं आया हूँ।
स्पेंसर रूपर्ट

1
क्या बिना कोशिश / कैच के ऐसा करने का कोई तरीका है? मुझे अपने उद्देश्यों के लिए किसी भी उपलब्ध पोर्ट का उपयोग करने में कोई आपत्ति नहीं होगी , लेकिन पोर्ट नंबर पर पुनरावृत्ति और प्रत्येक पर एक-एक करके कोशिश / पकड़ने-आईएनजी जब तक मैं एक मुक्त एक बेकार मिल रहा है। कहीं 'देशी बूलियन उपलब्ध नहीं है' (int) विधि, जो सिर्फ जांच करती है?
ओरेन शॉवेल

27
नया सेवस्केटबोर्ड (0) अपने आप एक मुफ्त पोर्ट का चयन करेगा।
स्पेंसर रूपर्ट

10

निम्नलिखित समाधान स्प्रिंग-कोर (अपाचे लाइसेंस) के सॉकेट यूटिल्स से प्रेरित है ।

अन्य समाधानों की तुलना में Socket(...)यह बहुत तेज़ है (एक सेकंड से भी कम समय में 1000 टीसीपी पोर्ट का परीक्षण):

public static boolean isTcpPortAvailable(int port) {
    try (ServerSocket serverSocket = new ServerSocket()) {
        // setReuseAddress(false) is required only on OSX, 
        // otherwise the code will not work correctly on that platform          
        serverSocket.setReuseAddress(false);
        serverSocket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), port), 1);
        return true;
    } catch (Exception ex) {
        return false;
    }
}       

3

सॉकेट आधारित समाधान आज़माएं / पकड़ें, सटीक परिणाम नहीं मिल सकते हैं (सॉकेट पता "लोकलहोस्ट" है और कुछ मामलों में पोर्ट को लूपबैक इंटरफ़ेस द्वारा "कब्जा" किया जा सकता है और कम से कम विंडोज पर मैंने यह परीक्षण विफल देखा है अर्थात विरोध झूठा उपलब्ध के रूप में घोषित)।

SIGAR नामक एक शांत पुस्तकालय है , निम्नलिखित कोड आपको हुक कर सकते हैं:

Sigar sigar = new Sigar();
int flags = NetFlags.CONN_TCP | NetFlags.CONN_SERVER | NetFlags.CONN_CLIENT;             NetConnection[] netConnectionList = sigar.getNetConnectionList(flags);
for (NetConnection netConnection : netConnectionList) {
   if ( netConnection.getLocalPort() == port )
        return false;
}
return true;

मुझे मिलता है: "java.library.path में कोई सिगार-x86-winnt.dll नहीं है" दुर्भाग्य से इसके लिए कुछ अतिरिक्त dll डाउनलोड करने की आवश्यकता होती है जो वास्तव में एंटरप्राइज़ वातावरण में व्यवहार्य नहीं है (मेरा सीआई सिस्टम पर कोई नियंत्रण नहीं है)। इतना बुरा .... वैसे भी धन्यवाद।
uthomas

@ हिंदुओं का अनुमान है कि आपके पास अभी भी आपके ऐप परिनियोजन पैकेज पर नियंत्रण है, अगर ऐसा है तो आप हमेशा सिगार देशी रनटाइम डीएलएल / एसओ अपने JARs के पास प्रदान कर सकते हैं और JAVA का काम कर सकते हैं। ऐप को JVM द्वारा लॉन्च किया गया है)।
शमिल द कैट

2

डेविड संतामरिया ने कहा कि उत्तर की सफाई:

/**
 * Check to see if a port is available.
 *
 * @param port
 *            the port to check for availability.
 */
public static boolean isPortAvailable(int port) {
    try (var ss = new ServerSocket(port); var ds = new DatagramSocket(port)) {
        return true;
    } catch (IOException e) {
        return false;
    }
}

यह अभी भी एक रेस स्थिति डेविड सेंटमारिया के जवाब देने के लिए टिप्पणी में user207421 द्वारा बताया के अधीन (कुछ बंदरगाह हड़पने सकता है के बाद इस विधि बंद कर देता है है ServerSocketऔर DatagramSocketऔर रिटर्न)।


1

मेरे मामले में यह पोर्ट से जुड़ने की कोशिश करने में मदद करता है - अगर सेवा पहले से मौजूद है, तो यह प्रतिक्रिया देगा।

    try {
        log.debug("{}: Checking if port open by trying to connect as a client", portNumber);
        Socket sock = new Socket("localhost", portNumber);          
        sock.close();
        log.debug("{}: Someone responding on port - seems not open", portNumber);
        return false;
    } catch (Exception e) {         
        if (e.getMessage().contains("refused")) {
            return true;
    }
        log.error("Troubles checking if port is open", e);
        throw new RuntimeException(e);              
    }

1
जो मांगा नहीं गया था।
लोर्ने

0

मेरे मामले में मुझे डाटाग्रामस्केट क्लास का उपयोग करना पड़ा।

boolean isPortOccupied(int port) {
    DatagramSocket sock = null;
    try {
        sock = new DatagramSocket(port);
        sock.close();
        return false;
    } catch (BindException ignored) {
        return true;
    } catch (SocketException ex) {
        System.out.println(ex);
        return true;
    }
}

पहले आयात करने के लिए मत भूलना

import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;

यह यूडीपी बंदरगाहों के लिए काम करता है। प्रश्न TCP पोर्ट के बारे में प्रतीत होता है।
लोर्न

-2

मैंने कुछ इस तरह की कोशिश की है और इसने मेरे साथ बहुत अच्छा काम किया है

            Socket Skt;
            String host = "localhost";
            int i = 8983; // port no.

                 try {
                    System.out.println("Looking for "+ i);
                    Skt = new Socket(host, i);
                    System.out.println("There is a Server on port "
                    + i + " of " + host);
                 }
                 catch (UnknownHostException e) {
                    System.out.println("Exception occured"+ e);

                 }
                 catch (IOException e) {
                     System.out.println("port is not used");

                 }

1
जो मांगा नहीं गया था।
लोरेन का

और एक सॉकेट लीक भी।
को लोर्न
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.