tpe*_*tpe 4 .net c# sockets wcf process
我在使用TCP绑定的自托管应用程序中有一个WCF服务.如果我从应用程序启动一个外部进程"commandLineApp",即使在我的应用程序关闭后仍然继续,我下次在我的应用程序启动WCF服务时会遇到问题.
WCF说地址/端口已经在使用中.如果在重新启动应用程序之前关闭外部应用程序(根本没有使用WCF或任何套接字),WCF服务就可以正常启动.
看起来我的应用程序中的套接字句柄以某种方式由新进程"commandLineApp"继承,并且在该进程退出之前不会被释放.
如何阻止其他进程从我的主应用程序继承句柄(或成为子进程?)?目前我正在使用Process.Start启动其他进程,使用UseShellExecute设置为False,因为我需要设置EnvironmentVarables和RedirectStandardOutput/Error.
我认为如果我设置UseShellExecute = true,则会阻止子进程设置,但是我没有得到我需要的所有功能.
有没有解决这个问题的方法?请参阅下面的示例代码
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "commandLineApp.exe";
psi.Arguments = "/someParameter";
psi.EnvironmentVariables.Add("...", "...");
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
Process process = new Process();
process.StartInfo = psi;
process.Start();
// Monitor if process with PID = process.Id is running
// ...
Run Code Online (Sandbox Code Playgroud)
编辑 - 附加信息:执行"netstat -noa"表示该端口与主应用程序的先前PID一起使用状态LISTEN,但不再有该PID的进程.一旦我关闭"commandLineApp",netstat命令就不再列出该端口了.
在主应用程序退出之前,WCF服务将像这样关闭:
try
{
serviceHost.Close(TimeSpan.FromSeconds(4));
}
catch (Exception)
{
serviceHost.Abort();
}
Run Code Online (Sandbox Code Playgroud)
我在上面的评论中错了:SO_REUSEADDR仅在句柄被关闭时才适用,但似乎套接字句柄确实是由子进程继承的,并且没有简单的方法可以防止这种情况.这似乎是一个非常愚蠢的设计决定,特别是因为有些地方指出如果安装了任何LSP,则不能在子代中使用句柄.
如果您对调用有更多控制权WSASocket,则可以传递该WSA_FLAG_NO_HANDLE_INHERIT标志,但这在WCF内部很难实现.这里有几个其他选择:
选项#1:自己调用CreateProcess并传递FALSE给bInheritHandles.
选项#2:在设置WCF(或任何其他套接字)之前创建一个帮助程序进程.通过命名管道与它通信.从此帮助程序而不是从主进程启动子进程.