C# 确定进程正在使用的网络适配器

C# 确定进程正在使用的网络适配器,c#,.net,networking,C#,.net,Networking,我在谷歌上看到过几个类似的问题,但没有一个完全符合我的想法。我正在制作一个减少延迟的程序(用于游戏),当某个进程打开时,它基本上会降低用户的MTU,当进程关闭时,它会恢复。但是,MTU是特定于网络适配器的设置,有些用户有多个连接的网络适配器。为此,我想让程序也检测游戏正在使用的适配器,并且只更改该适配器上的MTU会很好 游戏一次只使用一个适配器 我不能硬编码终端服务器IP地址,因为它们变化相当频繁。它似乎存在必须是一种确定另一个进程正在使用哪个适配器而不知道终端IP地址的方法,但我似乎找不到它

我在谷歌上看到过几个类似的问题,但没有一个完全符合我的想法。我正在制作一个减少延迟的程序(用于游戏),当某个进程打开时,它基本上会降低用户的MTU,当进程关闭时,它会恢复。但是,MTU是特定于网络适配器的设置,有些用户有多个连接的网络适配器。为此,我想让程序也检测游戏正在使用的适配器,并且只更改该适配器上的MTU会很好

游戏一次只使用一个适配器

我不能硬编码终端服务器IP地址,因为它们变化相当频繁。它似乎存在必须是一种确定另一个进程正在使用哪个适配器而不知道终端IP地址的方法,但我似乎找不到它

编辑: 多亏了蝉和雷姆科,我解决了这个问题

我使用了Remco链接到()的ManagedPhelper类,Cicada的评论将我引向了这篇文章()

将它们与一些(讨厌的、非常未优化的)LINQ结合起来,我得到了这个代码片段,它接受进程名并返回它正在使用的网络接口,如果找不到,则返回null

    private NetworkInterface getAdapterUsedByProcess(string pName)
    {
        Process[] candidates = Process.GetProcessesByName(pName);
        if (candidates.Length == 0)
            throw new Exception("Cannot find any running processes with the name " + pName + ".exe");

        IPAddress localAddr = null;
        using (Process p = candidates[0])
        {
            TcpTable table = ManagedIpHelper.GetExtendedTcpTable(true);
            foreach (TcpRow r in table)
                if (r.ProcessId == p.Id)
                {
                    localAddr = r.LocalEndPoint.Address;
                    break;
                }
        }

        if (localAddr == null)
            throw new Exception("No routing information for " + pName + ".exe found.");

        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            IPInterfaceProperties ipProps = nic.GetIPProperties();
            if (ipProps.UnicastAddresses.Any(new Func<UnicastIPAddressInformation, bool>((u) => { return u.Address.ToString() == localAddr.ToString(); })))
                return nic;
        }
        return null;
    }
专用网络接口GetAdapterUserByProcess(字符串pName)
{
Process[]候选者=Process.GetProcessesByName(pName);
if(candidates.Length==0)
抛出新异常(“找不到任何名为“+pName+”.exe”的正在运行的进程”);
IPAddress localAddr=null;
使用(流程p=候选者[0])
{
TcpTable table=ManagedIpHelper.GetExtendedTcpTable(true);
foreach(表中的TcpRow r)
if(r.ProcessId==p.Id)
{
localAddr=r.LocalEndPoint.Address;
打破
}
}
if(localAddr==null)
抛出新异常(“未找到“+pName+”.exe的路由信息”);
foreach(NetworkInterface.GetAllNetworkInterfaces()中的NetworkInterface nic)
{
IPInterfaceProperties ipProps=nic.GetIPProperties();
if(ipProps.unicastaddress.Any(新函数((u)=>{return u.Address.ToString()==localAddr.ToString();})))
返回网卡;
}
返回null;
}
测试证实这是完美的!非常感谢,伙计们

使用此代码段的任何人的旁注:

  • 您将需要managediHelper类
  • 根据具体情况,您的应用程序可能需要请求提升
  • 多个正在运行的进程(想想Chrome)将返回一个未定义的结果。如果您要将此代码用于多文件进程candiate情况,我强烈建议您将使用(进程p=候选者[0])更改为更具体的过滤器,即基于PID的过滤器
  • 您可能还希望实现新的异常类型,例如,您可以更清晰地捕获“无路由信息”,原因是此错误通常通过等待一段时间(让目标进程打开连接)然后重试来修复

除了蝉,这必须帮助你:

它是一个围绕一些C/C++代码的C#包装器,它可以为您提供所有打开的连接以及相关PID(进程Id)的列表


我相信这是唯一的方法,根据可执行路径/名称确定进程(id),并尝试查找该进程的当前连接。

如果找到该进程使用的本地端点,则知道它使用的适配器。你不能这样做吗?嗯,我不控制进程,所以我不知道如何去做。嗯
netstat-a
提供进程使用的本地端点。然后必须将IP映射到适当的适配器。(也许还有更简单的方法)。减少MTU如何减少滞后?您最好为自己的套接字使用套接字发送/接收缓冲区大小、Nagle设置等。我怀疑用户是否会善待他们的全局NIC设置被篡改。在Nagle关闭后降低MTU会增加发送到服务器的数据包数量,因此缩短响应时间。MTU仅在用户允许时设置。此外,我无法控制游戏的套接字,因此这里没有运气。如果进程在多个子网上有连接,那么这项工作的效果如何?@JohnSaunders,该条件尚未定义。您可能会收到所有正在使用的适配器,然后您将不得不选择一个。。。。您可以通过匹配远程和本地端点来“缩小范围”,但这种方法无法达到使用这种方法的目的(在不知道终端IP的情况下查找适配器)。幸运的是,我正在观看的过程只打开了一个连接……我不确定“未定义”是什么意思。总的来说,这是一个完全正确的情况。如果您也觉得它在一般情况下是有效的,那么我希望您更新您的问题,以表明在您的特定情况下,将永远不会有多个适配器。我的意思是未定义,如“您首先获得的适配器不一致”。将按您的建议进行编辑。