最近的一个项目中需要同时使用两块网卡收发UDP组播数据包,并且要求使用Socket的方式接收和发送网络数据包(我不会告诉你们我之前是直接使用SharpPcap来实现的)。在C#中Socket接触的比较早,但是用的不多,特别是在实现本次上网卡的收发过程中也是遇到了不少麻烦。其中最最头疼的就是不能同时接收两张网卡的数据,虽然这个问题不是致命的(大不了用SharpPcap呗!!),但是最为一个21世纪有志青年,怎么能干出这种半吊子的事情呢!于是,这两天我陷入了这个问题无法自拔,当然,最后还是解决了!哈~哈~哈哈哈~~

就在解决问题的那瞬间,眼前忽然出现了一个身影——“啊~~勤劳的(码)农夫啊~~,请问你丢的是这把金斧头呢,还是这…….”,“金斧头!金斧头!”(嘿嘿,把它卖了就能炒股票!赚大钱!出任CEO!迎娶白富美!走向人生巅峰!)

啊~~~呸!呸!呸!其实我想说,良心发现的我还是觉得如果有那么一群人还在纠结这个问题的,那么看看这里,也许能有帮助。(真的!绝对不是来装X的)

问题概述

言归正传,在我的应用中,我主要是想利用C#的Socket来接收组播的UDP数据包。当然,发送也需要,但不是我最关心的问题。因此,我首先想到的就是UdpClient这个类。这个类对Socket进行了很好的封装,用起来更加简单。那么问题来了,我始终只能收到一个网卡上的数据,这是很头疼的。我检查了网络,检查了数据包发现都没问题,但就是只能收到其中一个网卡的数据。

下面是我初始化Socket的代码,该代码为CapDevice类中的一段:

// 定义IPEndPoint
private IPEndPoint localEP = null;
private IPEndPoint remoteEP = null; // 定义UDP发送和接收Socket
//private Socket udpReceive = null;
private UdpClient udpReceive = null;
private UdpClient udpSend = null; // 本机节点
localEP = new IPEndPoint(device, LOCAL_PORT); // 远程节点
remoteEP = new IPEndPoint(IPAddress.Parse(MASTER_IP), DES_PORT); // 实例化
udpReceive = new UdpClient(AddressFamily.InterNetwork);
udpReceive.Client.ReceiveBufferSize = 320000;
udpReceive.Client.Bind(localEP);
udpReceive.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpSend = new UdpClient(); // 发送和接收加入组播组
udpReceive.JoinMulticastGroup(IPAddress.Parse(MASTER_TX_GROUP));
udpSend.JoinMulticastGroup(IPAddress.Parse(MASTER_RX_GROUP));

// 打开发送标志位
isOpen = true; // 打开接收线程
cap_thread = new Thread(new ThreadStart(ReceiveLoop));
cap_thread.Start();
cap_thread.Priority = ThreadPriority.Highest;
cap_thread.IsBackground = true;

在使用过程中,我分别实例化了两个CapDevice对象,并且将所需IP和端口信息通过参数传入。

device为本机网卡的IP地址;

LOCAL_PORT为本机侦听端口;

MASTER_IP为待接收的远程设备的IP地址;

DES_PORT为待接收的远程设备的端口;

MASTER_TX_GROUP为接收数据绑定的组;

MASTER_RX_GROUP为发送数据绑定的组;

本人使用台式机开发,主板自带一张千兆网卡,然后外接了一张PCI接口的千兆网卡。在我调试和寻找问题的过程中遇到这样的情况:

1. 两张网卡的IP分别为192.168.30.33和192.168.30.34,33的为主板上的网卡,34的是外接的网卡。按照上述方式进行配置后我发现我永远只能收到33的网卡上的数据,除非我拔掉33的网卡上的网线,并且重新打开接收,此时34的网卡上才会有数据。

2. 我尝试使用同步、异步的方法,并且尝试使用Socket类而不是UdpClient类,但是都没有成功。

因此,我怀疑,即使我的Socket侦听的IP是192.168.30.34,实际Windows还是没有对34这张网卡的数据进行侦听。

问题解决

我花了很多时间去寻找答案,但是结果还是不太对。最终我找到一个讲述跟我一样问题的网站:

http://stackoverflow.com/questions/15265620/udp-read-data-from-all-network-interfaces

提出问题的人也遇到了同样的问题,并且进行了很多尝试。最终他得到的结论是:“把同步接收改成异步接收就行啦!”

我试了一下,发现问题不在那里,还是没有。但是我发现一个地方,那就是加入组的时候他们使用的JoinMulticastGroup函数有两个参数,然后我这么改了:

udpReceive.JoinMulticastGroup(IPAddress.Parse(MASTER_TX_GROUP), localEP.Address);

恩,其实看了这么多,我就想说这个,真不好意思,浪费大家这么多时间看废话,嘻嘻!!

第二个参数是本地地址,真正能够让我的第二张网卡也能够接收数据的也是这个参数,看来第二个参数才是通知系统将IP与本地网卡建立联系。测试了一下,异步接收和同步接收都没有问题。

总结

问题总结一句话,加入组播组需要使用带本地IP地址的重载函数。当然,写这么多就是想把问题描述清楚一点,同样的问题按照这里所述就能得到解决。如果是其它原因导致Socket通信失败,按照本文所述就不一定能解决咯。

下面是初始化代码(区别就在高亮部分代码):

// 定义IPEndPoint
private IPEndPoint localEP = null;
private IPEndPoint remoteEP = null; // 定义UDP发送和接收Socket
//private Socket udpReceive = null;
private UdpClient udpReceive = null;
private UdpClient udpSend = null; // 本机节点
localEP = new IPEndPoint(device, LOCAL_PORT); // 远程节点
remoteEP = new IPEndPoint(IPAddress.Parse(MASTER_IP), DES_PORT); // 实例化
udpReceive = new UdpClient(AddressFamily.InterNetwork);
udpReceive.Client.ReceiveBufferSize = 320000;
udpReceive.Client.Bind(localEP);
udpReceive.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpSend = new UdpClient(); // 发送和接收加入组播组
udpReceive.JoinMulticastGroup(IPAddress.Parse(MASTER_TX_GROUP), localEP.Address);
udpSend.JoinMulticastGroup(IPAddress.Parse(MASTER_RX_GROUP));

// 打开发送标志位
isOpen = true; // 打开接收线程
cap_thread = new Thread(new ThreadStart(ReceiveLoop));
cap_thread.Start();
cap_thread.Priority = ThreadPriority.Highest;
cap_thread.IsBackground = true;

这里顺便把我同步接收线程函数也贴出来吧:

private void ReceiveLoop()
{ byte[] rcvData; while (isOpen)
{
rcvData = udpReceive.Receive(ref remoteEP);
// 解析数据
UploadEndecoder.CapturePkgM(rcvData);
} udpReceive.Close();
udpSend.Close();
}

Socket的双网卡收发(C#)的更多相关文章

  1. CentOS工作内容(六)双网卡带宽绑定bind teaming

    CentOS工作内容(六)双网卡带宽绑定bind  teaming Teaming功能是什么功能http://zhidao.baidu.com/link?url=cpcwl9LH4FSHJBaTW-e ...

  2. 烂泥:VMWare Workation双网卡配置IP地址

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 前几天给一个客户做远程项目实施,客户那边的服务器是Windows OS的,我们这边的业务 ...

  3. Linux下双网卡绑定bond0

    一:原理: linux操作系统下双网卡绑定有七种模式.现在一般的企业都会使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多.而一般企业都会使用linux操作系统下自带的网卡绑 ...

  4. Linux 双网卡绑定

    Linux 双网卡绑定 Linux 双网卡绑定双网卡绑定的常用模式:mode1:active-backup 模式,即主备模式.mode0:round-broin 模式,即负载均衡模式(需要交换机配置聚 ...

  5. Windows Server 2008 双网卡同时上内外网 不能正常使用

    Windows server 2008 32位下,双网卡同时上内外网,并提供VPN服务,遇见的奇怪问题 1.服务器配置 2.网络配置 以太网适配器 内部连接: 连接特定的 DNS 后缀 . . . . ...

  6. CentOS 7使用nmcli配置双网卡聚合

    进入CentOS 7以后,网络方面变化比较大,例如eth0不见了,ifconfig不见了,其原因是网络服务全部都由NetworkManager管理了,下面记录下今天下午用nmcli配置的网卡聚合,网络 ...

  7. VirtualBox双网卡搭建Linux虚拟实验环境

    VirtualBox中有如下几种网络连接方式: NAT(NAT到宿主机IP地址) NAT Network (NAT到宿主机所在的网段,即使用相同的网关和掩码) Bridged Adapter Inte ...

  8. ubuntu 双线双网卡双IP实现方式

    昨天金桥机房上架了一台多玩的测试机,系统是ubuntu9.04 X64的系统,母机IBM X336机器.用户需求是双线,故采用一个网卡配置电信地址,另一个网卡配置联通地址,安装好系统后配置好IP发现联 ...

  9. (转)深度分析Linux下双网卡绑定七种模式

    现在一般的企业都会 使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多.而一般企业都会使用linux操作系统下自带的网卡绑定模式,当然现在 网卡产商也会出一些针对window ...

随机推荐

  1. 通过Migration在EF6中用多个DbContext

    通过Migration在EF6中用多个DbContext EF EF6 C# Migration 通过Migration在EF6中用多个DbContext 前言 实现目标 设置多数据上下文 更新数据脚 ...

  2. JS数组(Array)处理函数总结

    1.concat() 连接两个或更多的数组该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.例如: <script type="text/javascript"&g ...

  3. 遍历input。select option 选中的值

    <label> <input name="Fruit" type="radio" value="0" class=&quo ...

  4. MySQL语法

    sql(structure query language)结构化查询语言ansi iso/iec组织制定ddl(data definition language) 数据定义语言dml(manipula ...

  5. 软件工程 speedsnail 冲刺5

    2015-5-9 完成任务:学习了黑马android教学视频10\11\12集,填写游戏人的姓名功能为明天的记分板准备: 遇到问题: 问题1 Suspicious method call; shoul ...

  6. 【转】详解JavaScript中的this

    ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...

  7. windows实用技巧

    电脑如今已经非常普及,不过目前大多数电脑系统都是Win7/Win8.1或者Win10.你真的对自己电脑系统了解吗?今天小编为大家分享13个实用电脑技巧,会这些电脑技巧才叫牛哦! 13个实用电脑技巧 一 ...

  8. 基于jQuery编写的横向自适应幻灯片切换特效

    基于jQuery编写的横向自适应幻灯片切换特效 全屏自适应jquery焦点图切换特效,在IE6这个蛋疼的浏览器兼容性问题上得到了和谐,兼容IE6. 适用浏览器:IE6.IE7.IE8.360.Fire ...

  9. 【转】CSS white-space 属性

    定义和用法 white-space 属性设置如何处理元素内的空白. 这个属性声明建立布局过程中如何处理元素中的空白符.值 pre-wrap 和 pre-line 是 CSS 2.1 中新增的. 默认值 ...

  10. 关于VS2012下安装破解文件Visual Assit X的一点说明

    今天在使用Visual Studio 2012的时候,编写代码的助手Visual Assit X突然提示我说,试用期已过,要求我输入一个注册码,我靠,这货不是几个月前已经破解了吗,怎么今天傻不愣登的提 ...