C#でTcpClientを使用するため、または一般的にソケットに接続するために、特定のポートがマシンで空いているかどうかを最初に確認するにはどうすればよいですか?
詳細: これは私が使用するコードです:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
C#でTcpClientを使用するため、または一般的にソケットに接続するために、特定のポートがマシンで空いているかどうかを最初に確認するにはどうすればよいですか?
詳細: これは私が使用するコードです:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
回答:
を使用しているためTcpClient
、開いているTCPポートをチェックしていることになります。System.Net.NetworkInformation名前空間には、多くの優れたオブジェクトがあります。
IPGlobalProperties
オブジェクトを使用してオブジェクトの配列を取得し、TcpConnectionInformation
エンドポイントのIPとポートについて問い合わせることができます。
int port = 456; //<--- This is your value
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
{
if (tcpi.LocalEndPoint.Port==port)
{
isAvailable = false;
break;
}
}
// At this point, if isAvailable is true, we can proceed accordingly.
netstat -a -b
。にはLISTENING
接続が存在しないことに注意してくださいGetActiveTcpConnections()
。また、にチェックすべきSystem.Net.IPEndPoints[]
で返されるipGlobalProperties.GetActiveTcpListeners();
あなたはIntertubeの間違った終わりにいます。特定のポートを1つだけ開くことができるのはサーバーです。いくつかのコード:
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
try {
TcpListener tcpListener = new TcpListener(ipAddress, 666);
tcpListener.Start();
}
catch (SocketException ex) {
MessageBox.Show(ex.Message, "kaboom");
}
失敗する:
通常、各ソケットアドレス(プロトコル/ネットワークアドレス/ポート)の使用は1つだけ許可されます。
TCP接続をセットアップする場合、4タプル(source-ip、source-port、dest-ip、dest-port)は一意である必要があります。これは、パケットが正しい場所に配信されるようにするためです。
サーバー側では、着信ポート番号にバインドできるサーバープログラムがさらに制限されています(1つのIPアドレスを想定しています。マルチNICサーバーには他の機能もありますが、ここでは説明する必要はありません)。
したがって、サーバー側では次のようになります。
クライアント側では、通常は少し簡単です。
宛先IP /ポートが一意である必要はありません。一度に1人しかGoogleを使用できず、ビジネスモデルがかなり破壊されるためです。
つまり、ソースポートのみが異なる複数のセッションをセットアップし、チャンクを並行してダウンロードできるため、マルチセッションFTPなどの不思議なことをすることさえできます。トレントは、各セッションの宛先が通常異なるという点で少し異なります。
そして、すべてのわずらわしさ(申し訳ありませんが)の後、特定の質問に対する答えは、空きポートを指定する必要がないということです。送信元ポートを指定しない呼び出しでサーバーに接続している場合、ほぼ確実にゼロが使用され、システムは未使用のポートを提供します。
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...どのようにしたら、特定のポートがマシン上で空いているかを最初に確認できますか?
つまり、他のアプリケーションでは使用されていません。アプリケーションがポートを使用している場合、解放されるまで他のユーザーはそのポートを使用できません。–アリ
ここで何が起こっているのかを誤解しています。
TcpClient(...)パラメータは、接続先のサーバーIPとサーバーポートです。
TcpClientは、サーバーと通信するために、利用可能なプールから一時的なローカルポートを選択します。ローカルポートがwinsockレイヤーによって自動的に処理されるため、ローカルポートの可用性を確認する必要はありません。
上記のコードフラグメントを使用してサーバーに接続できない場合、問題はいくつかの1つ以上である可能性があります。(つまり、サーバーのIPやポートが間違っている、リモートサーバーが利用できない、など)
このヒントをありがとう。同じ機能が必要ですが、サーバー側でポートが使用されているかどうかを確認するため、このコードに変更しました。
private bool CheckAvailableServerPort(int port) {
LOG.InfoFormat("Checking Port {0}", port);
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
foreach (IPEndPoint endpoint in tcpConnInfoArray) {
if (endpoint.Port == port) {
isAvailable = false;
break;
}
}
LOG.InfoFormat("Port {0} available = {1}", port, isAvailable);
return isAvailable;
}
-anb
)を使用してアプリケーションのPIDを提供するのと同じ情報を提供せず、パラメーターなしで外部接続と状態を表示します。
答えjroをありがとう。私は自分の使い方に合わせて微調整する必要がありました。ポートがリッスンされていて、必ずしもアクティブになっていないかどうかを確認する必要がありました。これのために私は交換しました
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
と
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
エンドポイントの配列を繰り返して、ポート値が見つからないことを確認しました。
string hostname = "localhost";
int portno = 9081;
IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0];
try
{
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) // Port is in use and connection is successful
MessageBox.Show("Port is Closed");
sock.Close();
}
catch (System.Net.Sockets.SocketException ex)
{
if (ex.ErrorCode == 10061) // Port is unused and could not establish connection
MessageBox.Show("Port is Open!");
else
MessageBox.Show(ex.Message);
}
netstat!これは、Windowsに同梱されているネットワークコマンドラインユーティリティです。現在確立されているすべての接続と、現在リッスンされているすべてのポートが表示されます。このプログラムを使用して確認できますが、コードから確認する場合は、System.Net.NetworkInformation名前空間を調べますか?2.0以降の新しい名前空間です。そこにいくつかの良いものがあります。しかし、結局、netstatコマンドを介して入手できる同じ種類の情報を取得したい場合は、結果としてP / Invokeを実行する必要があります...
その名前空間には、ネットワークについて理解するために使用できる一連のクラスが含まれています。
私はその古いコードを見つけることができませんでしたが、自分で同様の何かを書くことができると思います。まず、IP Helper APIをチェックしてください。GetTcpTable WINAPI関数用のGoogle MSDN およびP / Invokeを使用して、必要な情報が得られるまで列挙します。
あなたは言う
つまり、他のアプリケーションでは使用されていません。アプリケーションがポートを使用している場合、解放されるまで他のユーザーはそのポートを使用できません。
しかし、何かがそのポートでリッスンしている場合、他のユーザーがポートを使用している間はいつでもポートに接続できます。そうしないと、httpポート80が混乱します。
もしあなたの
c = new TcpClient(ip, port);
失敗した場合は、何も聞いていません。それ以外の場合は、他のマシン/アプリケーションがそのIPおよびポートに対して開いているソケットを持っている場合でも、接続します。
利用可能なポートから私は除外します:
次のインポートでは:
using System.Net.NetworkInformation;
次の関数を使用して、ポートが使用可能かどうかを確認できます。
private bool isPortAvalaible(int myPort)
{
var avalaiblePorts = new List<int>();
var properties = IPGlobalProperties.GetIPGlobalProperties();
// Active connections
var connections = properties.GetActiveTcpConnections();
avalaiblePorts.AddRange(connections);
// Active tcp listners
var endPointsTcp = properties.GetActiveTcpListeners();
avalaiblePorts.AddRange(endPointsTcp);
// Active udp listeners
var endPointsUdp = properties.GetActiveUdpListeners();
avalaiblePorts.AddRange(endPointsUdp);
foreach (int p in avalaiblePorts){
if (p == myPort) return false;
}
return true;
}
VB.NETを使用するユーザーのために、同様の機能を提供します。
Imports System.Net.NetworkInformation
Private Function isPortAvalaible(ByVal myPort As Integer) As Boolean
Dim props As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()
' ignore active connections
Dim tcpConnInfoArray() As TcpConnectionInformation = props.GetActiveTcpConnections()
For Each tcpi As Net.NetworkInformation.TcpConnectionInformation In tcpConnInfoArray
If tcpi.LocalEndPoint.Port = myPort Then
Return False
End If
Next tcpi
' ignore active TCP listeners
Dim activeTcpListeners() As Net.IPEndPoint = props.GetActiveTcpListeners
For Each tcpListener As Net.IPEndPoint In activeTcpListeners
If tcpListener.Port = myPort Then
Return False
End If
Next tcpListener
' ignore active UPD listeners
Dim activeUdpListeners() As Net.IPEndPoint = props.GetActiveUdpListeners
For Each udpListener As Net.IPEndPoint In activeUdpListeners
If udpListener.Port = myPort Then
Return False
End If
Next udpListener
Return True
End Function
dotnet core 3.1で空きポートを見つけるという正確な質問に答えるために(これは私のユニットテストで必要なものです)、私はこれを思いつきました
public static int GetAvailablePort(IPAddress ip) {
TcpListener l = new TcpListener(ip, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
Log.Info($"Available port found: {port}");
return port;
}
注:ポート0に関する@ user207421のコメントに基づいて、私はこれを検索して見つけ、わずかに変更しました。
チェックを行ってから接続を試行するまでの時間枠には、いくつかのプロセスでポート-クラシックTOCTOUが使用される場合があることに注意してください。接続してみませんか?失敗した場合は、ポートが利用できないことがわかります。
リモートTCPサービスに接続するためにローカルマシンで開いているポートを知る必要はありません(特定のローカルポートを使用する場合を除きますが、通常はそうではありません)。
すべてのTCP / IP接続は、リモートIP、リモートポート番号、ローカルIP、ローカルポート番号の4つの値で識別されますが、接続を確立するために必要なのは、リモートIPとリモートポート番号だけです。
を使用してtcp接続を作成する場合
TcpClient c; c =新しいTcpClient(remote_ip、remote_port);
システムは、多くの空きローカルポート番号の1つを接続に自動的に割り当てます。何もする必要はありません。リモートポートが開いているかどうかを確認することもできます。しかし、それを接続しようとするよりも、それを行うためのより良い方法はありません。
public static bool TestOpenPort(int Port)
{
var tcpListener = default(TcpListener);
try
{
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
tcpListener = new TcpListener(ipAddress, Port);
tcpListener.Start();
return true;
}
catch (SocketException)
{
}
finally
{
if (tcpListener != null)
tcpListener.Stop();
}
return false;
}
test_connection("ip", port);
public void test_connection(String hostname, int portno) {
IPAddress ipa = (IPAddress)Dns.GetHostAddresses(hostname)[0];
try {
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) {
MessageBox.Show("Port is in use");
}
sock.Close();
}
catch (System.Net.Sockets.SocketException ex) {
if (ex.ErrorCode == 10060) {
MessageBox.Show("No connection.");
}
}
}