예제 #1
0
        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));
            }
        }
예제 #2
0
        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;
            }
        }