您的位置:首页 > 其它

Connection类之ConnectionIncomingData.cs(NetworkComms 2.3.1源码了解和学习)

2015-02-08 20:46 471 查看
networkComms.net2.3.1开源版本,基于gpl V3协议。因为不能公开3.x版本的源码,所以基于此版本进行学习。3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大。


/// <summary>
/// Connection对象  这个类是TcpConnection和 UDPConnnection连接类的父类
/// Connection由以下五个文件组成 大家注意到每个类前面都有个 partial关键字
/// ConnectionCreate.cs <1>
/// ConnectionDelegatesHandlers.cs <2>
/// ConnectionIncomingData.cs <3>
/// ConnectionSendClose.cs <4>
/// ConnectionStatic.cs  <5>
/// </summary>
/// 这部分负责接收数据,并交个networkcomms的优先级线程池处理
public abstract partial class Connection
{
/// <summary>
/// The <see cref="PacketBuilder"/> for this connection
/// </summary>
protected PacketBuilder packetBuilder;

/// <summary>
/// The current incoming data buffer
/// </summary>
protected byte[] dataBuffer;

/// <summary>
/// The total bytes read so far within dataBuffer
/// </summary>
protected int totalBytesRead;

/// <summary>
/// The thread listening for incoming data should we be using synchronous methods.
/// </summary>
protected Thread incomingDataListenThread = null;

/// <summary>
/// A connection specific method which triggers any requisites for accepting incoming data
/// </summary>
protected abstract void StartIncomingDataListen();

/// <summary>
/// Attempts to use the data provided in packetBuilder to recreate something usefull. If we don't have enough data yet that value is set in packetBuilder.
/// </summary>
/// <param name="packetBuilder">The <see cref="PacketBuilder"/> containing incoming cached data</param>
protected void IncomingPacketHandleHandOff(PacketBuilder packetBuilder)
{
try
{
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... checking for completed packet with " + packetBuilder.TotalBytesCached.ToString() + " bytes read.");

if (packetBuilder.TotalPartialPacketCount == 0)
throw new Exception("Executing IncomingPacketHandleHandOff when no packets exist in packetbuilder.");

//Loop until we are finished with this packetBuilder
int loopCounter = 0;
while (true)
{
//If we have ended up with a null packet at the front, probably due to some form of concatentation we can pull it off here
//It is possible we have concatenation of several null packets along with real data so we loop until the firstByte is greater than 0
if (packetBuilder.FirstByte() == 0)
{
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... null packet removed in IncomingPacketHandleHandOff() from " + ConnectionInfo + ", loop index - " + loopCounter.ToString());

packetBuilder.ClearNTopBytes(1);

//Reset the expected bytes to 0 so that the next check starts from scratch
packetBuilder.TotalBytesExpected = 0;

//If we have run out of data completely then we can return immediately
if (packetBuilder.TotalBytesCached == 0) return;
}
else
{
//First determine the expected size of a header packet
int packetHeaderSize = packetBuilder.FirstByte() + 1;

//Do we have enough data to build a header?
if (packetBuilder.TotalBytesCached < packetHeaderSize)
{
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... ... more data required for complete packet header.");

//Set the expected number of bytes and then return
packetBuilder.TotalBytesExpected = packetHeaderSize;
return;
}

//We have enough for a header
PacketHeader topPacketHeader;
using(MemoryStream headerStream = packetBuilder.ReadDataSection(1, packetHeaderSize - 1))
topPacketHeader = new PacketHeader(headerStream, NetworkComms.InternalFixedSendReceiveOptions);

//Idiot test
if (topPacketHeader.PacketType == null)
throw new SerialisationException("packetType value in packetHeader should never be null");

//We can now use the header to establish if we have enough payload data
//First case is when we have not yet received enough data
if (packetBuilder.TotalBytesCached < packetHeaderSize + topPacketHeader.PayloadPacketSize)
{
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... ... more data required for complete packet payload. Expecting " + (packetHeaderSize + topPacketHeader.PayloadPacketSize).ToString() + " total packet bytes.");

//Set the expected number of bytes and then return
packetBuilder.TotalBytesExpected = packetHeaderSize + topPacketHeader.PayloadPacketSize;
return;
}
//Second case is we have enough data
else if (packetBuilder.TotalBytesCached >= packetHeaderSize + topPacketHeader.PayloadPacketSize)
{
//We can either have exactly the right amount or even more than we were expecting
//We may have too much data if we are sending high quantities and the packets have been concatenated
//no problem!!
SendReceiveOptions incomingPacketSendReceiveOptions = IncomingPacketSendReceiveOptions(topPacketHeader);
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Debug("Received packet of type '" + topPacketHeader.PacketType + "' from " + ConnectionInfo + ", containing " + packetHeaderSize.ToString() + " header bytes and " + topPacketHeader.PayloadPacketSize.ToString() + " payload bytes.");

//If this is a reserved packetType we call the method inline so that it gets dealt with immediately
bool isReservedType = false;
foreach (var tName in NetworkComms.reservedPacketTypeNames)
{
//isReservedType |= topPacketHeader.PacketType == tName;
if (topPacketHeader.PacketType == tName)
{
isReservedType = true;
break;
}
}

//Only reserved packet types get completed inline
if (isReservedType)
{
#if WINDOWS_PHONE
var priority = QueueItemPriority.Normal;
#else
var priority = (QueueItemPriority)Thread.CurrentThread.Priority;
#endif

PriorityQueueItem item = new PriorityQueueItem(priority, this, topPacketHeader, packetBuilder.ReadDataSection(packetHeaderSize, topPacketHeader.PayloadPacketSize), incomingPacketSendReceiveOptions);
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... handling packet type '" + topPacketHeader.PacketType + "' inline. Loop index - " + loopCounter.ToString());
NetworkComms.CompleteIncomingItemTask(item);
}
else
{
QueueItemPriority itemPriority = (incomingPacketSendReceiveOptions.Options.ContainsKey("ReceiveHandlePriority") ? (QueueItemPriority)Enum.Parse(typeof(QueueItemPriority), incomingPacketSendReceiveOptions.Options["ReceiveHandlePriority"]) : QueueItemPriority.Normal);
PriorityQueueItem item = new PriorityQueueItem(itemPriority, this, topPacketHeader, packetBuilder.ReadDataSection(packetHeaderSize, topPacketHeader.PayloadPacketSize), incomingPacketSendReceiveOptions);

//QueueItemPriority.Highest is the only priority that is executed inline
#if !WINDOWS_PHONE
if (itemPriority == QueueItemPriority.Highest)
{
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... handling packet type '" + topPacketHeader.PacketType + "' with priority HIGHEST inline. Loop index - " + loopCounter.ToString());
NetworkComms.CompleteIncomingItemTask(item);
}
else
{
int threadId = NetworkComms.CommsThreadPool.EnqueueItem(item.Priority, NetworkComms.CompleteIncomingItemTask, item);
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... added completed " + item.PacketHeader.PacketType + " packet to thread pool (Q:" + NetworkComms.CommsThreadPool.QueueCount.ToString() + ", T:" + NetworkComms.CommsThreadPool.CurrentNumTotalThreads.ToString() + ", I:" + NetworkComms.CommsThreadPool.CurrentNumIdleThreads.ToString() + ") with priority " + itemPriority.ToString() + (threadId > 0 ? ". Selected threadId=" + threadId.ToString() : "") + ". Loop index=" + loopCounter.ToString() + ".");
}
#else
int threadId = NetworkComms.CommsThreadPool.EnqueueItem(item.Priority, NetworkComms.CompleteIncomingItemTask, item);
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... added completed " + item.PacketHeader.PacketType + " packet to thread pool (Q:" + NetworkComms.CommsThreadPool.QueueCount.ToString() + ", T:" + NetworkComms.CommsThreadPool.CurrentNumTotalThreads.ToString() + ", I:" + NetworkComms.CommsThreadPool.CurrentNumIdleThreads.ToString() + ") with priority " + itemPriority.ToString() + (threadId > 0 ? ". Selected threadId=" + threadId.ToString() : "") + ". Loop index=" + loopCounter.ToString() + ".");
#endif
}

//We clear the bytes we have just handed off
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Removing " + (packetHeaderSize + topPacketHeader.PayloadPacketSize).ToString() + " bytes from incoming packet buffer from connection with " + ConnectionInfo +".");
packetBuilder.ClearNTopBytes(packetHeaderSize + topPacketHeader.PayloadPacketSize);

//Reset the expected bytes to 0 so that the next check starts from scratch
packetBuilder.TotalBytesExpected = 0;

//If we have run out of data completely then we can return immediately
if (packetBuilder.TotalBytesCached == 0) return;
}
else
throw new CommunicationException("This should be impossible!");
}

loopCounter++;
}
}
catch (Exception ex)
{
//Any error, throw an exception.
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Fatal("A fatal exception occured in IncomingPacketHandleHandOff(), connection with " + ConnectionInfo + " be closed. See log file for more information.");

NetworkComms.LogError(ex, "CommsError");
CloseConnection(true, 45);
}
}

/// <summary>
/// Handle an incoming CheckSumFailResend packet type
/// </summary>
/// <param name="packetDataSection"></param>
internal void CheckSumFailResendHandler(MemoryStream packetDataSection)
{
//If we have been asked to resend a packet then we just go through the list and resend it.
SentPacket packetToReSend;
lock (sentPacketsLocker)
{
string checkSumRequested = NetworkComms.InternalFixedSendReceiveOptions.DataSerializer.DeserialiseDataObject<string>(packetDataSection,
NetworkComms.InternalFixedSendReceiveOptions.DataProcessors, NetworkComms.InternalFixedSendReceiveOptions.Options);

if (sentPackets.ContainsKey(checkSumRequested))
packetToReSend = sentPackets[checkSumRequested];
else
throw new CheckSumException("There was no packet sent with a matching check sum");
}

//If we have already tried resending the packet 10 times something has gone horribly wrong
if (packetToReSend.SendCount > 10) throw new CheckSumException("Packet sent resulted in a catastropic checksum check exception.");

if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Warn(" ... resending packet due to MD5 mismatch.");

//Increment send count and then resend
packetToReSend.IncrementSendCount();
SendPacket(packetToReSend.Packet);
}
}


www.networkcomms.cn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐