原因
因为我们做工业控制,电脑必然存在多个网口,常见的连接类型:
- 多个相机,每个相机会使用单独的千兆网卡,并且使用六类网线;
- 各个需要控制或者调用的下位机;
- 上传数据的上位机。
现场的网络环境复杂,存在很多不可空的因素,最常见的就是,连接下位机的socket会通过上传数据的网口连接到别的设备上,影响我们的设备正常运行。
结论
因此,我们需要绑定网卡来连接下位机。
代码如下
string BindMac ="AAAAAAAAAA";//计划绑定的网卡的物理地址
string IPLocal = string.Empty;
IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
Console.WriteLine("Interface information for {0}.{1} ",
computerProperties.HostName, computerProperties.DomainName);
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
Console.WriteLine(adapter.Description);
Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length, '='));
Console.WriteLine(" Interface type .......................... : {0}", adapter.NetworkInterfaceType);
Console.WriteLine(" Physical Address ........................ : {0}",
adapter.GetPhysicalAddress().ToString());
Console.WriteLine(" Is receive only.......................... : {0}", adapter.IsReceiveOnly);
Console.WriteLine(" Multicast................................ : {0}", adapter.SupportsMulticast);
//获取单播地址集
UnicastIPAddressInformationCollection ipCollection = properties.UnicastAddresses;
foreach (UnicastIPAddressInformation ipadd in ipCollection)
{
if (ipadd.Address.AddressFamily == AddressFamily.InterNetwork)
{
string ipv44 = ipadd.Address.ToString();//获取ip
string mac = adapter.GetPhysicalAddress().ToString();
Console.WriteLine("IP:{0}\tMac:{1}", ipv44, mac);
if (mac == BindMac)
{
IPLocal = ipv44;
break;
}
}
else if (ipadd.Address.AddressFamily == AddressFamily.InterNetworkV6)
{
//本机IPV6 地址
}
}
if (!string.IsNullOrEmpty(IPLocal)) break;
Console.WriteLine();
}
最终,我们使用获取到的“IPLocal”,绑定socket,然后通过下位机的IP地址来连接,确保连接的网卡正确。
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connectSuccess = false;
socket.Bind(new IPEndPoint(IPAddress.Parse(IPLocal), 0)); //绑定本地通讯使用的网卡IP
socket.Connect(System.Net.IPAddress.Parse(IPAdress), Port);//连接下位机