2016-09-21 10 views
2

私はC++プロジェクトを開発中です。要件の1つを満たすために、ポートがいつでもアプリケーションで使用できるかどうかを確認する必要があります。これを実現するために、私はこの解決策に来ました。ここでC++を使用してlinuxで使用できるポートがあるかどうかを調べる

#include <iostream> 
#include <cstdlib> 
#include <stdexcept> 
#include <string> 
#include <stdio.h> 


std::string _executeShellCommand(std::string command) { 
    char buffer[256]; 
    std::string result = ""; 
    const char * cmd = command.c_str(); 
    FILE* pipe = popen(cmd, "r"); 
    if (!pipe) throw std::runtime_error("popen() failed!"); 

    try { 
     while (!feof(pipe)) 
      if (fgets(buffer, 128, pipe) != NULL) 
       result += buffer; 
    } catch (...) { 
     pclose(pipe); 
     throw; 
    } 
    pclose(pipe); 
    return result; 
} 

bool _isAvailablePort(unsigned short usPort){ 
    char shellCommand[256], pcPort[6]; 
    sprintf(shellCommand, "netstat -lntu | awk '{print $4}' | grep ':' | cut -d \":\" -f 2 | sort | uniq | grep %hu", usPort); 
    sprintf(pcPort, "%hu", usPort); 

    std::string output = _executeShellCommand(std::string(shellCommand)); 

    if(output.find(std::string(pcPort)) != std::string::npos) 
      return false; 
    else 
      return true; 

} 


int main() { 
    bool res = _isAvailablePort(5678); 
    return 0; 
} 

基本的に_executeShellCommand機能は、いつでも任意のシェルコマンドをexcuteことができ、戻り文字列としてstdout出力を返すことができます。

そして、私はその機能で次のシェルコマンドを実行しています。ポートが既に使用中である場合

netstat -lntu | awk '{print $4}' | grep ':' | cut -d \":\" -f 2 | sort | uniq | grep portToCheck 

ので、_executeShellCommandはPortValue自身を返し、そうでなければ、空白が返されます。返された文字列をチェックすることで、私は決めることができます。

これまでのところとても良いです。

今、私は自分のプロジェクトを完全にクラッシュプルーフにしたいと思っています。だから、netstatコマンドを実行する前に、本当に存在するかどうかを確認したい。私はこの場合に助けが必要です。私は知っている、それはLinuxマシンでnetstatコマンドの可用性を疑うのは馬鹿だ。何らかの理由で自分のマシンからnetstatバイナリを削除したユーザーを考えているだけです。

N.B. :私はポートが利用可能であるかどうかチャックにbind()コールをしたくありません。また、_executeShellCommandを別の時間(つまり、別のシェルコマンドを実行しないで)呼び出すことなく、netstatコマンドが利用可能かどうかを確認することができます。

+0

あなたは 'whereisはのnetstat'かそこらのように使用し、出力を確認することができ、よりコマンドがあります。 –

+0

チェックと使用する間にポートが利用できなくなるケースを処理する必要があることに注意してください。コンテキストに応じて、それが利用可能であることを確認することは役に立たないか、チェックしたい時にポートの所有権を取る方が良いでしょう。 – AProgrammer

+0

'bind()'を使わない特別な理由はありますか? – karastojko

答えて

4

さらに良い考えは、コードが完全にnetstatなしで動作するようにすることです。

Linuxの場合、すべてnetstat(ご使用の場合)は、使用中のすべてのポートを列挙する/proc/net/tcpの内容が読み込まれます。

あなたがしなければならないことは、自分自身で/proc/net/tcpを開き、それを解析することです。これは単なる普通の退屈なファイル解析コードになります。それよりはるかに「クラッシュプルーフ」を得ることはできません。

/proc/net/tcpという形式のドキュメントは、Linuxのマニュアルページにあります。

UDPポートを確認する必要がある場合は、/proc/net/udpとなります。

もちろん、/proc/net/tcpにチェックを入れてから、誰かがそのポートをつかむことができる間にレースウィンドウがあります。しかし、これはまたnetstatでも同様です。それはずっと遅いプロセスになるので、これは実際には改善され、レースウィンドウが大幅に縮小されます。

+0

これはかなり良い、実現可能な解決策です。どうもありがとう。 –

0

netstatコマンドが利用できるかどうかを確認する方法を尋ねるので、私はC++で他の方法を提案しようとしません。 netstatバイナリが$PATHで利用可能である場合、コマンドは0を返し、

command -v netstat 

:シェルの方法は、次のコマンドのリターンコードをチェックしています。バッシュでは、通常、次のようになります。

command -v netstat 
if [ $? -eq 0 ]; then 
    netstat # ... 
else 
    echo >&2 "Error: netstat is not available" 
fi 

それとも単に

command -v netstat >/dev/null && netstat # ... 
関連する問題