}
}
+
+ [TestMethod]
+ public void UdpUnreliableDataSubsetSendTest()
+ {
+ using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296, IPMode.IPv4)))
+ using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)))
+ {
+ listener.Start();
+ listener.NewConnection += delegate (object sender, NewConnectionEventArgs e)
+ {
+ e.Connection.DataReceived += delegate (object s, DataReceivedEventArgs evt)
+ {
+ Assert.IsTrue(Enumerable.SequenceEqual(evt.Bytes, new byte[] { 3, 4 }));
+ };
+ };
+
+ connection.Connect();
+ connection.SendBytes(new byte[] { 1, 2, 3, 4, 5, 6 }, 2, 2, SendOption.None);
+ }
+ }
+
/// <summary>
/// Tests IPv4 connectivity.
/// </summary>
using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296)))
using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296)))
{
- TestHelper.RunServerToClientTest(listener, connection, (int)(connection.FragmentSize * 9.5), SendOption.FragmentedReliable);
+ TestHelper.RunServerToClientTest(listener, connection, (int)(UdpConnection.FragmentSize * 9.5), SendOption.FragmentedReliable);
}
}
using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296)))
using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296)))
{
- TestHelper.RunClientToServerTest(listener, connection, (int)(connection.FragmentSize * 9.5), SendOption.FragmentedReliable);
+ TestHelper.RunClientToServerTest(listener, connection, (int)(UdpConnection.FragmentSize * 9.5), SendOption.FragmentedReliable);
}
}
/// </remarks>
public abstract void SendBytes(byte[] bytes, SendOption sendOption = SendOption.None);
+ /// <summary>
+ /// Sends a number of bytes to the end point of the connection using the specified <see cref="SendOption"/>.
+ /// </summary>
+ /// <param name="bytes">The bytes of the message to send.</param>
+ /// <param name="offset"></param>
+ /// <param name="length"></param>
+ /// <param name="sendOption">The option specifying how the message should be sent.</param>
+ /// <remarks>
+ /// <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
+ /// <para>
+ /// The sendOptions parameter is only a request to use those options and the actual method used to send the
+ /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
+ /// general any implementer should aim to always follow the user's request.
+ /// </para>
+ /// </remarks>
+ public abstract void SendBytes(byte[] bytes, int offset, int length, SendOption sendOption = SendOption.None);
+
/// <summary>
/// Connects the connection to a server and begins listening.
/// </summary>
//Copy data to new array
byte[] bytes = new byte[bytesReceived];
Buffer.BlockCopy(dataBuffer, 0, bytes, 0, bytesReceived);
-
+
//Begin receiving again
try
{
/// <summary>
/// The amount of data that can be put into a fragment.
/// </summary>
- public int FragmentSize { get { return fragmentSize; } }
- int fragmentSize = 65507 - 1 - 2 - 2 - 2;
+ public const int FragmentSize = 65507 - 1 - 2 - 2 - 2;
/// <summary>
/// The last fragmented message ID that was written.
/// <summary>
/// Sends the bytes reliably and stores the send.
/// </summary>
- /// <param name="bytes">The byte array to write to.</param>
+ /// <param name="sendOption"></param>
+ /// <param name="data">The byte array to write to.</param>
/// <param name="ackCallback">The callback to make once the packet has been acknowledged.</param>
void ReliableSend(byte sendOption, byte[] data, Action ackCallback = null)
{
- byte[] bytes = new byte[data.Length + 3];
+ this.ReliableSend(sendOption, data, 0, data.Length, ackCallback);
+ }
+
+ /// <summary>
+ /// Sends the bytes reliably and stores the send.
+ /// </summary>
+ /// <param name="sendOption"></param>
+ /// <param name="data">The byte array to write to.</param>
+ /// <param name="offset"></param>
+ /// <param name="length"></param>
+ /// <param name="ackCallback">The callback to make once the packet has been acknowledged.</param>
+ void ReliableSend(byte sendOption, byte[] data, int offset, int length, Action ackCallback = null)
+ {
+ byte[] bytes = new byte[length + 3];
//Add message type
bytes[0] = sendOption;
//Add reliable ID
AttachReliableID(bytes, 1, ackCallback);
-
+
//Copy data into new array
- Buffer.BlockCopy(data, 0, bytes, bytes.Length - data.Length, data.Length);
+ Buffer.BlockCopy(data, offset, bytes, bytes.Length - length, length);
//Write to connection
WriteBytesToConnection(bytes);
- Statistics.LogReliableSend(data.Length, bytes.Length);
+ Statistics.LogReliableSend(length, bytes.Length);
}
/// <summary>
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
HandleSend(bytes, (byte)sendOption);
}
+ /// <summary>
+ /// Sends a number of bytes to the end point of the connection using the specified <see cref="SendOption"/>.
+ /// </summary>
+ /// <param name="bytes">The bytes of the message to send.</param>
+ /// <param name="offset"></param>
+ /// <param name="length"></param>
+ /// <param name="sendOption">The option specifying how the message should be sent.</param>
+ /// <remarks>
+ /// <include file="DocInclude/common.xml" path="docs/item[@name='Connection_SendBytes_General']/*" />
+ /// <para>
+ /// The sendOptions parameter is only a request to use those options and the actual method used to send the
+ /// data is up to the implementation. There are circumstances where this parameter may be ignored but in
+ /// general any implementer should aim to always follow the user's request.
+ /// </para>
+ /// </remarks>
+ public override void SendBytes(byte[] bytes, int offset, int length, SendOption sendOption = SendOption.None)
+ {
+ //Early check
+ if (State != ConnectionState.Connected)
+ throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
+
+
+ //Inform keepalive not to send for a while
+ ResetKeepAliveTimer();
+
+ switch (sendOption)
+ {
+ //Handle reliable header and hellos
+ case SendOption.Reliable:
+ ReliableSend((byte)sendOption, bytes, offset, length);
+ break;
+
+ case SendOption.FragmentedReliable:
+ throw new NotImplementedException();
+ // FragmentedSend(data);
+ // break;
+
+ //Treat all else as unreliable
+ default:
+ UnreliableSend((byte)sendOption, bytes, offset, length);
+ break;
+ }
+ }
+
/// <summary>
/// Handles the reliable/fragmented sending from this connection.
/// </summary>
//Treat all else as unreliable
default:
- UnreliableSend(data, sendOption);
+ UnreliableSend(sendOption, data);
break;
}
}
}
}
+ /// <summary>
+ /// Sends bytes using the unreliable UDP protocol.
+ /// </summary>
+ /// <param name="sendOption">The SendOption to attach.</param>
+ /// <param name="data">The data.</param>
+ void UnreliableSend(byte sendOption, byte[] data)
+ {
+ this.UnreliableSend(sendOption, data, 0, data.Length);
+ }
+
/// <summary>
/// Sends bytes using the unreliable UDP protocol.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="sendOption">The SendOption to attach.</param>
- void UnreliableSend(byte[] data, byte sendOption)
+ /// <param name="offset"></param>
+ /// <param name="length"></param>
+ void UnreliableSend(byte sendOption, byte[] data, int offset, int length)
{
- byte[] bytes = new byte[data.Length + 1];
+ byte[] bytes = new byte[length + 1];
//Add message type
bytes[0] = sendOption;
-
+
//Copy data into new array
- Buffer.BlockCopy(data, 0, bytes, bytes.Length - data.Length, data.Length);
+ Buffer.BlockCopy(data, offset, bytes, bytes.Length - length, length);
//Write to connection
WriteBytesToConnection(bytes);
- Statistics.LogUnreliableSend(data.Length, bytes.Length);
+ Statistics.LogUnreliableSend(length, bytes.Length);
}
/// <summary>