internal asyncReceiveState(MSR.LST.Net.Sockets.Socket sock, BufferChunk bufferChunk, Queue queue, ReceivedFromCallback receivedFromCallback) { this.sock = sock; this.bufferChunk = bufferChunk; this.queue = queue; this.receivedFromCallback = receivedFromCallback; }
/// <summary> /// Receive a packet into a BufferChunk. This method is preferred over receiving into a byte[] because you can allocate a large /// byte[] in one BufferChunk and continously receiving into the buffer without recreating byte[]s and dealing with the memory allocation /// overhead that causes. /// /// No int bytes received is returned because the bytes received is stored in BufferChunk.Length. /// </summary> /// <param name="packetBuffer">BufferChunk</param> /// <example> /// ... /// MulticastUdpListener mcListener = new MulticastUdpListener(endPoint); /// /// // Allocate a 2K buffer to hold the incoming packet /// BufferChunk packetBuffer = new BufferChunk(2000); /// /// mcListener.Receive(packetBuffer); /// /// mcListener.Displose(); /// mcListener = null; /// ... /// </example> public void Receive(BufferChunk packetBuffer) { if (disposed) { throw new ObjectDisposedException("MulticastUdpListener already exposed"); } sock.Receive(packetBuffer); #if FaultInjection if (dropPacketsReceivedPercent > 0) { while (rnd.Next(0, 100) < dropPacketsReceivedPercent) { sock.Receive(packetBuffer); } } #endif }
/// <summary> /// Same as Receive, but you also get an EndPoint containing the sender of the packet. /// </summary> /// <param name="packetBuffer">BufferChunk</param> /// <param name="endPoint">EndPoint</param> /// <example> /// ... /// MulticastUdpListener mcListener = new MulticastUdpListener(endPoint); /// /// // Allocate a 2K buffer to hold the incoming packet /// BufferChunk packetBuffer = new BufferChunk(2000); /// /// // Allocate a structure to hold the incoming endPoint /// EndPoint endPoint; /// /// mcListener.ReceiveFrom(packetBuffer, endPoint); /// /// mcListener.Displose(); /// mcListener = null; /// ... /// </example> public void ReceiveFrom(BufferChunk packetBuffer, out EndPoint endPoint) { if (disposed) { throw new ObjectDisposedException("MulticastUdpListener already exposed"); } endPoint = new IPEndPoint(externalInterface, 0); sock.ReceiveFrom(packetBuffer, ref endPoint); #if FaultInjection if (dropPacketsReceivedPercent > 0) { while (rnd.Next(0, 100) < dropPacketsReceivedPercent) { sock.ReceiveFrom(packetBuffer, ref endPoint); } } #endif }
/// <summary> /// Send a BufferChunk. This method is preferred over sending a byte[] because you can allocate a large /// byte[] in one BufferChunk and continously send the buffer without recreating byte[]s and dealing with the memory allocation /// overhead that causes. /// </summary> /// <param name="packetBuffer">BufferChunk to send</param> public void Send(BufferChunk packetBuffer) { if (disposed) throw new ObjectDisposedException("UdpSender already disposed"); try { #if FaultInjection if (dropPacketsSentPercent == 0) { // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) sock.SendTo(packetBuffer, echoEndPoint); sock.SendTo(packetBuffer, endPoint); } else { // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) { if (rnd.Next(0, 100) >= dropPacketsSentPercent) { sock.SendTo(packetBuffer, echoEndPoint); } } if (rnd.Next(0, 100) >= dropPacketsSentPercent) { sock.SendTo(packetBuffer, endPoint); } } #else // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) sock.SendTo(packetBuffer, echoEndPoint); // Reset the retry counter retries = 0; // Come back to here in order to try resending to network RetrySend: try { sock.SendTo(packetBuffer, endPoint); if(delayBetweenPackets != 0) { Thread.Sleep(delayBetweenPackets); // To control bandwidth } } catch (SocketException se) { // Look for a WSACancelBlockingCall (Error code 10004) // We might just be in the middle of changing access points // This is a problem for the Intel 2200BG card if (se.ErrorCode == 10004) { if(retries++ < MaxRetries) { Thread.Sleep(DelayBetweenRetries); goto RetrySend; } } // Wrong error code or we have retried max times throw; } #endif } catch (SocketException se) { // Suppress the SocketException if the SocketException.NativeErrorCode is the same and the last exception occured within the exception suppression period if (lastExceptionNativeErrorCode == se.NativeErrorCode) { if (lastExceptionTime.AddSeconds(SecondsSuppressSocketExceptions) < DateTime.Now) { lastExceptionTime = DateTime.Now; throw; } } else { lastExceptionNativeErrorCode = se.NativeErrorCode; lastExceptionTime = DateTime.Now; throw; } } }
/// <summary> /// Send a BufferChunk. This method is preferred over sending a byte[] because you can allocate a large /// byte[] in one BufferChunk and continously send the buffer without recreating byte[]s and dealing with the memory allocation /// overhead that causes. /// </summary> /// <param name="packetBuffer">BufferChunk to send</param> public void Send(BufferChunk packetBuffer) { if (disposed) { throw new ObjectDisposedException("UdpSender already disposed"); } try { #if FaultInjection if (dropPacketsSentPercent == 0) { // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) { sock.SendTo(packetBuffer, echoEndPoint); } sock.SendTo(packetBuffer, endPoint); } else { // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) { if (rnd.Next(0, 100) >= dropPacketsSentPercent) { sock.SendTo(packetBuffer, echoEndPoint); } } if (rnd.Next(0, 100) >= dropPacketsSentPercent) { sock.SendTo(packetBuffer, endPoint); } } #else // Send an echo signal back if we're sending out to a unicast address. This mimicks the behavior of multicast with MulticastLoopback == true if (echoEndPoint != null) { sock.SendTo(packetBuffer, echoEndPoint); } // Reset the retry counter retries = 0; // Come back to here in order to try resending to network RetrySend: try { sock.SendTo(packetBuffer, endPoint); if (delayBetweenPackets != 0) { Thread.Sleep(delayBetweenPackets); // To control bandwidth } } catch (SocketException se) { // Look for a WSACancelBlockingCall (Error code 10004) // We might just be in the middle of changing access points // This is a problem for the Intel 2200BG card if (se.ErrorCode == 10004) { if (retries++ < MaxRetries) { Thread.Sleep(DelayBetweenRetries); goto RetrySend; } } // Wrong error code or we have retried max times throw; } #endif } catch (SocketException se) { // Suppress the SocketException if the SocketException.NativeErrorCode is the same and the last exception occured within the exception suppression period if (lastExceptionNativeErrorCode == se.NativeErrorCode) { if (lastExceptionTime.AddSeconds(SecondsSuppressSocketExceptions) < DateTime.Now) { lastExceptionTime = DateTime.Now; throw; } } else { lastExceptionNativeErrorCode = se.NativeErrorCode; lastExceptionTime = DateTime.Now; throw; } } }
/// <summary> /// Copy the valid data section of 'this' to the destination BufferChunk /// overwriting dest's previous contents /// This method does not allow dest's valid data section to grow or shrink /// (i.e. treat valid data as a fixed buffer) /// </summary> /// <param name="destination">BufferChunk</param> /// <param name="index">offset in the destination BufferChunk's valid data</param> public void CopyTo(BufferChunk destination, int index) { ValidateObject(destination); ValidateNonNegative(index); ValidateNotZeroLength(this.length); ValidateSufficientSpace(this.length, destination.length - index); Array.Copy(this.buffer, this.index, destination.buffer, destination.index + index, this.length); }
/// <summary> /// Same as Receive, but you also get an EndPoint containing the sender of the packet. /// </summary> /// <param name="packetBuffer">BufferChunk</param> /// <param name="endPoint">EndPoint</param> /// <example> /// ... /// MulticastUdpListener mcListener = new MulticastUdpListener(endPoint); /// /// // Allocate a 2K buffer to hold the incoming packet /// BufferChunk packetBuffer = new BufferChunk(2000); /// /// // Allocate a structure to hold the incoming endPoint /// EndPoint endPoint; /// /// mcListener.ReceiveFrom(packetBuffer, endPoint); /// /// mcListener.Displose(); /// mcListener = null; /// ... /// </example> public void ReceiveFrom(BufferChunk packetBuffer, out EndPoint endPoint) { if (disposed) throw new ObjectDisposedException("MulticastUdpListener already exposed"); endPoint = new IPEndPoint(externalInterface,0); sock.ReceiveFrom(packetBuffer, ref endPoint); #if FaultInjection if ( dropPacketsReceivedPercent > 0 ) { while (rnd.Next(0,100) < dropPacketsReceivedPercent) { sock.ReceiveFrom(packetBuffer, ref endPoint); } } #endif }
/// <summary> /// Receive a packet into a BufferChunk. This method is preferred over receiving into a byte[] because you can allocate a large /// byte[] in one BufferChunk and continously receiving into the buffer without recreating byte[]s and dealing with the memory allocation /// overhead that causes. /// /// No int bytes received is returned because the bytes received is stored in BufferChunk.Length. /// </summary> /// <param name="packetBuffer">BufferChunk</param> /// <example> /// ... /// MulticastUdpListener mcListener = new MulticastUdpListener(endPoint); /// /// // Allocate a 2K buffer to hold the incoming packet /// BufferChunk packetBuffer = new BufferChunk(2000); /// /// mcListener.Receive(packetBuffer); /// /// mcListener.Displose(); /// mcListener = null; /// ... /// </example> public void Receive(BufferChunk packetBuffer) { if (disposed) throw new ObjectDisposedException("MulticastUdpListener already exposed"); sock.Receive(packetBuffer); #if FaultInjection if ( dropPacketsReceivedPercent > 0 ) { while (rnd.Next(0,100) < dropPacketsReceivedPercent) { sock.Receive(packetBuffer); } } #endif }