ポート3000をリッスンするアプリを開発しています。起動してもリスナーを作成できないため、インスタンスがまだポートをリッスンしているようです(C#、TcpListener、ただし無関係です)。取った。
今、アプリはタスクマネージャに存在しないので、私はそのPIDを見つけてそれを殺そうとしましたが、この興味深い結果につながりました:
C:\Users\username>netstat -o -n -a | findstr 0.0:3000
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 3116
C:\Users\username>taskkill /F /PID 3116
ERROR: The process "3116" not found.
私は前にこの振る舞いを見たことがなく、誰かが解決策を持っているかどうかを確認するのに十分おもしろいと考えました。
アップデート:私はProcess Explorerを起動し、3000を検索しましたが、これが見つかりました:
<Non-existent Process>(3000): 5552
私はそれを右クリックして "Close Handle"を選びました。 Process Explorerではなくなりましたが、それでもnetstatに表示され、アプリによるリスナーの起動が停止されます。
更新2:プロセスを"<non-existent>"
として表示する TCPView for Windows が見つかりました。 CurrPortsと同様に、このツールで接続を閉じようとしても何も起こりません。
ソケットでの無限の待機を避けるために、あなたのプログラムはSO_REUSEADDRとSO_RCVTIMEOパラメータで setsockopt関数 を使うべきです:
SO_REUSEADDR : Allows the socket to be bound to an address that is already in use.
SO_RCVTIMEO : Sets the timeout, in milliseconds, for blocking receive calls.
同じ問題があり、Microsoft Sysinternalsの Process Explorer を使用して、存在しなくなったプロセスIDを調べます。
そのプロセスがいくつかのDrWatsonプロセスによって参照されていたことがわかります。それらのプロセスを強制終了するとportが解放されました。 DrWatsonはMicrosoftへのメモリダンプの送信に使用されていましたが、クラッシュしたプロセスがその時点で数十GBのメモリを保持していたため、これには数時間かかりました。
考えられる問題は、あなたのプロセスがソケットハンドルを継承した別の(子)プロセスを開始し、それがまだ実行中であるということです。
これを防ぐには、さまざまな方法があります。例えば、 ProcessStartInfo.UseShellExecute = true;
CurrPorts を試してみるべきだと思う
CurrPortsは、ローカルコンピュータで現在開かれているすべてのTCP/IPおよびUDPポートのリストを表示するネットワーク監視ソフトウェアです。リスト内の各ポートについて、ポートを開いたプロセスに関する情報(プロセス名、プロセスのフルパス、プロセスのバージョン情報(製品名、ファイルの説明など))も表示されます。プロセスが作成され、それを作成したユーザー。
さらに、CurrPortsでは、不要なTCP接続を閉じ、ポートを開いたプロセスを終了し、TCP/UDPポート情報をHTMLファイル、XMLファイル、またはタブ区切りテキストファイル
CurrPortsはまた、身元不明のアプリケーションが所有する不審なTCP/UDPポートを自動的にピンク色でマークします(バージョン情報とアイコンがないアプリケーション)。
ここでlingerという用語に言及する必要があります。
詳細は http://msdn.Microsoft.com/ja-jp/library/ms739165.aspx にあります。
簡単に言うと、未送信のデータが存在する場合にソケットが閉じられた後でもソケットを開いたままにするようにソケットシステムに指示するオプションがあります。
C#アプリでは、Socket.SetSocketOptionを介して関連オプションを指定できます。 http://msdn.Microsoft.com/ja-jp/library/1011kecd.aspx
ここに挙げたものはすべて送信とクライアントに関するものですが、同様の問題がありました。さらに検索した結果、上の例に示すようにリスナーにlingerオプションを指定できることがわかりました。 http://msdn.Microsoft.com/library/system.net.sockets.tcplistener.server.aspx
同僚の中には、アプリケーションの終了/終了後に約2分間OSがポートを保持していると語った。それを考えると、ポートが一定時間後にまだ保留されているかどうかを聞くのは面白いでしょう。
私は同じ問題を抱えていて、それによってそれを直しました:
netstat -o
でPIDを見つけるNetstatは時々pidを返すことができますが、対応する実行ファイル名を返さないことに注意してください
あなたはProcess Explorerでプロセスを見ることができますか?もしそうであれば、そこからそれをkillすることができますが、実際にそれが何であるかを調べた後に限ります(あなたはプロセスに読み込まれたすべてのdllを見ることができます)
私もこの問題に遭遇しました。ついに私は自分の理由を見つけた。これは、メインプロセスがc/c ++でpopenによって子プロセスを呼び出したことが原因です。しかし、pcloseを起動する前にメインプロセスがクラッシュ/シャットダウンします。それから、portはまだメインプロセスを処理し、まだそれを監視します。
根本的な原因がいくつかの子プロセスがポートを継承して作成され、子プロセスがまだポートを保持している間に親プロセスがクラッシュしたときに同様の問題が発生しました。解決策は、まだ実行中の子プロセスを識別して停止することでした。この例では、存在しないプロセスPIDは7336でした。
> wmic process get processid,parentprocessid | findstr/i 7336
7336 23828
このプロセスを停止するには
> taskkill /f /pid 23828
そしてこれで問題は解決しました。
私はxdebugと同じ問題を抱えていました、それはポート9000を開いたままにしました。
私は "taskkill/pid xxxx"を使ってcmdで閉じることができました。
ポートを使用しているプロセスのpidは、 "netstat -o"で取得できます。
私の設定は7ホームプレミアムを獲得しました。
Netstatコマンドに '-b'フラグを付けてみてください。ポートを使用している実行可能ファイルの名前がわかります。それからタスクマネージャでそのprocを見つけて、そこで殺してください。それでもうまくいかない場合は、実行可能ファイルがポートを開いたままにしているものを投稿してください。
問題は、停止したプロセスが1つ以上の子プロセスを開始した場合に発生する可能性があります。もし
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);
子プロセスを起動するために使用されていましたが、継承ハンドルの値に依存します。
bInheritHandles = false
親プロセスが停止し、クライアントプロセスがまだ実行中の場合、Windowsはポートをブロックしません。
ファイアーウォールがインストールされているとは思いませんか(または、Windowsのネットワーク機能を試してみたか)。
ファイアウォールの中には、このような動作をするものがあり、ポートを開いたままにしておくことができます。
持っている場合は、それを無効にしてからプログラムを起動して閉じ、何が起こるかを確認してください。
私はこれと同じ問題を抱えていました。プロセスはクラッシュしている間にデバッグされていましたが、まだ中断された状態のvsjitdebugger.exeプロセスが残っていました。 vsjitdebugger.exeプロセスを強制終了すると、問題が解決しました。
あなたのプロセスはシステムとしてリストされているので、たぶんあなたは "システム"コマンドプロンプトでそれを殺すことができます。システムアカウントには、通常の管理者よりも多くの権限があります。
Cmd.exeのタスクをスケジュールすることで "System" cmd.exeを取得できます(スケジューラはSystemとして実行されます)。
at 15:23 /interactive "cmd.exe"
近い将来に何かのためにその時間を変更してください。マシンコンソールにいることも確認してください(通常のターミナルサーバーセッションにいる場合は、新しいcmd.exeは表示されません。コンソールにmstsc
ログインします)。他にも方法があると思いますが、これは過去には私にとって役に立ちました。
TCPViewとProcess Explorerのハイブリッド使用は私のために働きました;)私は最初にTCPViewでポートを使用していたプロセスIDを調べました。 Process Explorerでプロセスを分離し、Process Explorerを使用してプロセスを強制終了しました。