public void DeQueueData(out s2h.ExData[] exData) { // remove all received data from the queues and prepare it for the client ArrayList l = new ArrayList(128); ArrayList toRemove = new ArrayList(16); exData = null; lock (m_Connections) { foreach (s2hConnection conn in m_Connections.Values) { int iCount = 0; lock (conn) { // NOTE: m_iWsTransmitBufferLen is a "SOFT" limit; that is, when the sum of // recv packets size exceed m_iWsTransmitBufferLen, the packet is sent. while (conn.DataRecievedQueue.Count > 0 && iCount < m_iWsTransmitBufferLen) { s2hConnectionData d = (s2hConnectionData)conn.DataRecievedQueue.Dequeue(); if (d == null) { continue; } s2h.ExData exd = new s2h.ExData(); exd.token = conn.handle; exd.data = d.data; l.Add(exd); if (d.data == null) { // a null packet in the queue // means connection closed by remote peer toRemove.Add(conn); break; } iCount += d.data.Length; } } } if (toRemove.Count > 0) { foreach (s2hConnection s in toRemove) { m_Connections.Remove(s); } toRemove.Clear(); } } if (l.Count > 0) { exData = (s2h.ExData[])l.ToArray(typeof(s2h.ExData)); } }
public void SendReceiveLocalSocketsLoop() { ArrayList toRemove = new ArrayList(128); int iSentData = 0; int iRecvData = 0; int iDataToSend = 0; bool bSomethingDone = false; byte [] recvData = new byte[1024 * 4]; try { for (;;) { bSomethingDone = false; lock (m_Connections) { foreach (s2hConnection conn in m_Connections.Values) { lock (conn) { // a connection not yet set ready by the client should be ignored if (!conn.bReady) { continue; } if (!conn.Connected && !conn.NullPacketSent) { // connection lost: push a null packet on the queue // to notify the WS Client conn.DataRecievedQueue.Enqueue(new s2hConnectionData(null, 0)); conn.NullPacketSent = true; continue; } ///////////////////////////////////////////// // send the pending data to the local socket ///////////////////////////////////////////// if (conn.CanSend && conn.DataToSendQueue.Count > 0) { bSomethingDone = true; // peek first packet s2hConnectionData buf = (s2hConnectionData)conn.DataToSendQueue.Peek(); if (buf.data == null) { // null packet: this means that the connection // has been closed on the WS Client side conn.Close(); toRemove.Add(conn.handle); } else { iDataToSend = buf.data.Length - buf.index; iSentData = conn.SendSimple(buf.data, buf.index, iDataToSend); if (iSentData < iDataToSend) { buf.index += iSentData; // partial data was sent } else { conn.DataToSendQueue.Dequeue(); // full data was sent } } } ///////////////////////////////////////////// // buffer the data received from local socket // NOTE: max of m_iMaxRecvDataQueueLen packets // are enqueued ///////////////////////////////////////////// if (conn.CanRecv && conn.DataRecievedQueue.Count < m_iMaxRecvDataQueueLen) { bSomethingDone = true; iRecvData = conn.RecvSimple(recvData, 0, recvData.Length); if (iRecvData == 0) { // connection was closed by remote peer // push a null packet on the queue // to notify the WS Client conn.Close(); conn.DataRecievedQueue.Enqueue(new s2hConnectionData(null, 0)); } else { byte[] data = new byte[iRecvData]; Array.Copy(recvData, 0, data, 0, iRecvData); s2hConnectionData buf = new s2hConnectionData(data, 0); conn.DataRecievedQueue.Enqueue(buf); } } } } // purge the closed connections foreach (string s in toRemove) { m_Connections.Remove(s); } toRemove.Clear(); } // sleep in case of inactivity; avoid 100% CPU // and allow context switch to other WebServices Recv/Send threads if (!bSomethingDone) { Thread.Sleep(20); } } } catch (ThreadInterruptedException) { return; } catch (ThreadAbortException) { Thread.ResetAbort(); return; } }