让我先说一下,套接字编程对我来说相当新鲜。此外,我问的代码已经工作了几年,我讨论的问题才开始,当我们从支持Windows XP改为Windows 7时。
我正在开发一个发送和接收网络数据包的C#应用程序。它是一种网络嗅探器类型的应用程序,因此数据完整性非常重要。自从我们从 Windows XP 迁移到 Windows 7 以来,当我们使用UDP广播(255.255.255.255)数据包时,我们会收到两次数据包。 (即我发送610个数据包,我收到1220个数据包)。
我已经使用WireShark验证了数据包只被接收一次。此外,我们还有一些旧的C ++套接字代码已被.NET代码替换。较旧的C ++代码不表示重复。这两个都表示发送了610个数据包,收到了610个数据包。
代码是高度线程化的,并且在各个类之间分开,但是将一些部分放在一起,接收代码如下所示:
public class RawSocket : Socket
{
public RawSocket( IPAddress address, int receiveBufferSize, bool receiveAll )
: base( AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP )
{
Bind( new IPEndPoint( address, 0 ) );
ReceiveBufferSize = receiveBufferSize;
ReceiveTimeout = 500; // half-a-second
if ( receiveAll ) {
byte[] incoming = BitConverter.GetBytes( 1 );
byte[] outgoing = BitConverter.GetBytes( 1 );
IOControl( IOControlCode.ReceiveAll, incoming, outgoing );
}
}
}
_device = new RawSocket( /* IP Address Specified Here */ );
然后在负责阅读的代码中......
byte[] buffer = new byte[ 65536 ];
int read = _device.Receive( buffer );
if (read > 0)
{
_packet = new byte[ size ];
_packet.BlockCopy( buffer, offset, size );
}
所以我的问题是,Windows XP和Windows 7之间的.NET套接字API会导致这种行为的变化是什么?我已阅读线程,表明存在差异,但没有这样的。跟踪代码使我认为它与Receive()
类上Socket
类的行为有关,可能有所不同。任何帮助将不胜感激!
答案 0 :(得分:5)
根据规范,这是预期的行为。
http://msdn.microsoft.com/en-us/library/system.net.sockets.iocontrolcode(v=vs.110).aspx表示ReceiveAll等于Winsock 2 SIO_RCVALL常量。
http://msdn.microsoft.com/en-us/library/windows/desktop/ee309610(v=vs.85).aspx说:
在Windows Server 2008及更早版本中,SIO_RCVALL IOCTL设置会 不捕获从网络接口发出的本地数据包。这个 包含在另一个接口上接收并转发出去的数据包 为SIO_RCVALL IOCTL指定的网络接口。
在Windows 7上 和Windows Server 2008 R2一样,这改变了本地数据包 发送出的网络接口也被捕获。这包括 在另一个接口上接收的数据包然后转发出去 使用SIO_RCVALL IOCTL绑定到套接字的网络接口。