最近做了一个Socket的DLL,主要实现的功能是给顶层仅提供数据包的接口。简化顶层程序在通讯方面的实现。
就是创建一个Client C1实例,必须使用给定的消息头格式,可以让C1发送数据包,从C1获取数据包。现在领导要求在其上包上一层,实现流量控制、窗口控制等功能,请大侠们指点一下,提供相关的参考书名。

解决方案 »

  1.   

    这个流量控制如果在dll中的话可能会有个问题。顶层没控制流量,向接口发送大量的数据,而dll中进行了流量控制就必须提供一个缓冲区来暂时存放没有发送出去的数据,这样长时间积累数据会导致占用大量的内存。
      

  2.   

    如果你这个DLL只供一个C1用,可以用变量来记录。
    如果是供多个上层程序用,就不行了。
    感觉你还是在上层直接记录的好。
      

  3.   

    所谓包一层实现流量控制和窗口控制,其实就是在发送数据之前先发送包头协议,这个协议你们可以自定义,比如第一到第八个字节里面写的是流量,第九到第十个字节写的是窗口数,如果这个太抽象,完全可以使用xml这种格式来发送指令。但是这样会提高发送和接收的成本。
      

  4.   


    在顶层程序控制和在DLL控制,如果数据量大于网络流量,都是要占电脑内存,
    在DLL中占用好像也没多大问题,我想先实现出来再对比效果。
      

  5.   


    是提供多个的,部分源代码:
        public class Client
        {
            //客户端事件
            public delegate void WiseClientEventHandle(int i);
        public event  WiseClientEventHandle OnReceivePacket = null;
        public event  WiseClientEventHandle OnConnected = null;
        public event  WiseClientEventHandle OnDisconnected = null;
            public delegate void WiseClientErrorHandle(string s);
            public event  WiseClientErrorHandle OnError = null;        internal event server.WiseServerEventHandle OnServerReceivePacket = null;
            internal event server.WiseServerEventHandle OnServerDisconnected = null;
            internal event server.WiseServerErrorHandle OnServerError = null;
            //类数据成员
            internal Socket _sock;
            private int _id;
            private string _addr;
            private int _port;
            private BaseMsgHeader _MH = null;
            private const int BUFFER_SIZE = 8192;
            private byte[] _buffer = new byte[8192];        private List<byte[]> ReceivePacketList = new List<byte[]>();
            private object ReceivePacketLock = new object();        private List<byte[]> SendPacketList = new List<byte[]>();
            private object SendPacketLock = new object();
            private bool _bSending = false;        private byte[] _receivebuffer = new byte[16384];
            private const int MAX_BUFFERSIZE = 16384;
            private int _ireceive = 0;        private byte[] _sendbuffer = new byte[8192];
            private int _isend = 0;        private AsyncCallback _connect_callback = null;
            private AsyncCallback _disconnect_callback = null;
            private AsyncCallback _receive_callback = null;
            private AsyncCallback _send_callback = null;
            //构造函数
            public Client(string addr, int port)
            {
                _addr = addr;
                _port = port;
                _MH = new DefaultMsgHeader();
            }        public Client(string addr, int port,BaseMsgHeader msgheader)
            {
                _addr = addr;
                _port = port;
                _MH = msgheader;
            }        internal Client(BaseMsgHeader msgheader,int id) 
            {
                _MH = msgheader;
                _id = id;
            }        //断开连接
            public void Disconnect()
            {
                try
                {
                    if (_disconnect_callback == null)
                        _disconnect_callback = new AsyncCallback(disconnect_callback);
                    _sock.BeginDisconnect(false, _disconnect_callback, _sock);
                }
                catch (Exception e)
                {
                    pdisconnect(0);
                    pError(e.Message);
                }
            }        private void disconnect_callback(IAsyncResult ar)
            {
                Socket s;
                try
                {
                    s = (Socket)ar.AsyncState;
                    s.EndDisconnect(ar);
                    pdisconnect(1);
                }
                catch (Exception e)
                {
                    pdisconnect(0);
                    pError(e.Message);
                }
            }        private void pdisconnect(int i)
            {
                if (OnDisconnected != null)
                    OnDisconnected(i);
                //即使服务应用程序有设置连接的OnDisconnect,也要发送信息到服务端
                if (OnServerDisconnected != null)
                    OnServerDisconnected(_id, i);
            }        private void pError(string s)
            {
                if (OnError != null)
                    OnError(s);
                else
                    if (OnServerError != null)
                        OnServerError(_id, s);
            }
            //连接
            public void Connect()
            {
                if (_connect_callback == null)
                    _connect_callback = new AsyncCallback(connect_callback);
                IPAddress[] ips = Dns.GetHostAddresses(_addr);
                IPEndPoint remotehost = new IPEndPoint(ips[0], _port);
                _sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _sock.BeginConnect(remotehost, _connect_callback, _sock);
            }        private void connect_callback(IAsyncResult ar)
            {
                Socket s;
                try
                {
                    s = (Socket)ar.AsyncState;
                    s.EndConnect(ar);
                    receive_data(s);
                    //if (_receive_callback == null)
                    //    _receive_callback = new AsyncCallback(receive_callback);                //s.BeginReceive(_buffer, 0, BUFFER_SIZE, 0, _receive_callback, s);                if (OnConnected != null)
                        OnConnected(1);             
                }
                catch (Exception e)
                {
                    if (OnConnected != null)
                        OnConnected(0);
                    if (OnError != null)        //服务端没有Connect
                        OnError(e.Message);
                }
            }        //接收数据包
            internal void receive_data(Socket s)
            {
                if (_receive_callback == null)
                    _receive_callback = new AsyncCallback(receive_callback);            s.BeginReceive(_buffer, 0, BUFFER_SIZE, 0, _receive_callback, s);
            }        private void receive_callback(IAsyncResult ar)
            {
                Socket s;
                int n;
                int nDeal;
                string strDebug;            try
                {
                    s = (Socket)ar.AsyncState;
                    n = s.EndReceive(ar);                if (n + _ireceive > MAX_BUFFERSIZE)
                    {
                        strDebug = "Error RecvCallback. Buffer Overload!";
                        pError(strDebug);
                        _ireceive = 0;
                    }
                    Array.Copy(_buffer, 0, _receivebuffer, _ireceive, n);
                    _ireceive += n;
                    if (_ireceive > 0)
                    {
                        nDeal = fill_packlist(_receivebuffer,_ireceive);
                        if (_ireceive >= nDeal)
                        {
                            Array.Copy(_receivebuffer, nDeal, _receivebuffer, 0, _ireceive - nDeal);
                            _ireceive -= nDeal;
                        }
                        if (ReceivePacketList .Count > 0)
                        {
                            //通知客户程序缓冲队列有数据包
                            pReceiveDate(ReceivePacketList.Count);
                        }
                    }
                    //当接收到0字节的时候,视为远端异常,连接断开
                    if (n == 0)
                    {
                        pError("RecvCallback Receive 0 Bytes. ");
                    }
                    else
                    {
                        receive_data(s);
                    }
                }
                catch (Exception e)
                {
                    pError(e.Message);
                }
            }
      

  6.   

            private void pReceiveDate(int i)
            {
                if (OnReceivePacket != null)
                    OnReceivePacket(i);
                else
                    if (OnServerReceivePacket != null)
                        OnServerReceivePacket(_id, i);
            }
            //根据包头类定义分析接收到的缓冲数据,把它分解成数据包
            //对每一个不同的包头进行处理
            private int fill_packlist(byte [] b,int len)
            {
                if (b == null || len == 0)
                    return 0;
                int nDeal = 0;            if (_MH is DefaultMsgHeader)
                {
                    do
                    {
                        // 查找包头标志 0xAAAAAAAA
                        while (len - nDeal >= 4 && BitConverter.ToUInt32(b, nDeal) != 0xAAAAAAAA)
                            nDeal++;                    if (len - nDeal < 12)
                        {   // 如果剩余数据不足包头长度(12字节),则返回                       
                            return nDeal;
                        }                    int packlen;
                        packlen = BitConverter.ToInt32(b, nDeal + 8);
                        if (nDeal + packlen > len)
                        {   // 剩余的数据不足包的长度                       
                            return nDeal;
                        }
                        else
                        {
                            byte[] packet = new byte[packlen];
                            Array.Copy(b, nDeal, packet, 0, packlen);
                            lock (ReceivePacketLock)
                            {
                                ReceivePacketList.Add(packet);
                            }
                            nDeal += packlen;
                        }
                    } while (true);
                }
                else if (_MH is ExchangeMsgHeader)
                {
                    //消息头长度为16,包长int,紧跟在消息头识别后面
                    do
                    {
                        // 查找包头标志 0xAAAAAAAA
                        while (len - nDeal >= 4 && BitConverter.ToUInt32(b, nDeal) != 0xAAAAAAAA)
                            nDeal++;                    if (len - nDeal < 16)
                        {   // 如果剩余数据不足包头长度(12字节),则返回                       
                            return nDeal;
                        }                    int packlen;
                        packlen = BitConverter.ToInt32(b, nDeal + 4);
                        if (nDeal + packlen > len)
                        {   // 剩余的数据不足包的长度                       
                            return nDeal;
                        }
                        else
                        {
                            byte[] packet = new byte[packlen];
                            Array.Copy(b, nDeal, packet, 0, packlen);
                            lock (ReceivePacketLock)
                            {
                                ReceivePacketList.Add(packet);
                            }
                            nDeal += packlen;
                        }
                    } while (true);
                }
                else  //暂时没有实现其他类
                {
                    pError("EnCounter Unknown MsgHeader!");
                    return 0;
                }        }        //发送数据
            public void SendPacket(byte [] b)
            {
                lock (SendPacketLock)
                {
                    if (_bSending)
                    {
                        SendPacketList.Add(b);
                    }
                    else
                    {
                        _bSending = true;
                        SendData(b,b.Length);
                    }
                }
            }        private void SendData(byte[] data, int n)
            {
                try
                {
                    if (n > 0 && data != null)
                    {
                        Array.Copy(data, 0, _sendbuffer, _isend, n);
                        _isend += n;                    if (_send_callback == null)
                            _send_callback = new AsyncCallback(send_callback);
                        _sock.BeginSend(_sendbuffer, 0, _isend, 0, _send_callback, _sock);
                    }            }
                catch (Exception e)
                {
                    pError(e.Message);
                }        }        private void send_callback(IAsyncResult ar)
            {
                Socket s;
                s = (Socket)ar.AsyncState;
                int n = s.EndSend(ar);
                if (_isend > n)
                {
                    Array.Copy(_sendbuffer, n, _sendbuffer, 0, _isend - n);
                    _isend -= n;
                    s.BeginSend(_sendbuffer, 0, _isend, 0, send_callback, s);
                }
                else
                {
                    _isend = 0;
                    lock (SendPacketLock)
                    {
                        if (SendPacketList.Count > 0)
                        {
                            SendData(SendPacketList[0], SendPacketList[0].Length);
                            SendPacketList.RemoveAt (0);
                        }
                        else
                            _bSending = false;
                    }
                }
            }        //关闭,释放资源
            public void CloseClient()
            {
                _buffer = null;
                ReceivePacketList = null;
                ReceivePacketLock = null;
                _receivebuffer = null;
                SendPacketList = null;
                SendPacketLock = null;
                _sendbuffer = null;
                if (_sock != null)
                    _sock.Close();
                //_sock = null;
            }        ///获取数据包
            public byte[] GetPacket()
            {
                if (ReceivePacketList.Count == 0 || ReceivePacketList == null)
                    return null;
                byte[] b;
                lock (ReceivePacketLock)
                {
                    b = ReceivePacketList[0];
                    ReceivePacketList.RemoveAt(0);
                }
                return b;
            }        //清空接收缓冲列表
            public void ClearArrived()
            {
                lock (ReceivePacketLock )
                {
                    ReceivePacketList.Clear();
                }
            }        //取得接收缓冲列表数据包数量
            public int ArrivedPacketCount
            {
                get { return ReceivePacketList.Count; }        
            }        //清空发送缓冲列表
            public void ClearSend()
            {
                lock (SendPacketLock)
                {
                    SendPacketList.Clear();
                }
            }        //取得发送缓冲列表数据包数量
            public int SendPacketCount
            {
                get { return SendPacketList.Count; }
            }        //取得连接的机器名称  ?
            public string ComputerName
            {
                get 
                {                
                    return ""; 
                }
            }        ///取得连接的IP地址
            public string LocalIP
            {
                get
                {
                    return ((IPEndPoint)_sock.LocalEndPoint).Address.ToString ();                
                }
            }        ///取得连接的端口
            public int LocalPort
            {
                get
                {
                    return ((IPEndPoint)_sock.LocalEndPoint).Port;
                }
            }        //取得标识
            public int ID
            {
                get { return _id; }
            }        public EndPoint LocalEndPoint
            {
                get { return _sock.LocalEndPoint; }
            }        public EndPoint RemoteEndPoint
            {
                get { return _sock.RemoteEndPoint; }
            }        ////设置类的消息头,让server端可用
            //internal BaseMsgHeader MsgHeader 
            //{
            //    get { return _MH; }
            //    set { _MH = value; }
            //}        //设置类的标识,让server端可用
            //internal int ClientID
            //{
            //    set { _id = value; }
            //}
        }    #region 消息头
        public class BaseMsgHeader
        {
        }    public class DefaultMsgHeader : BaseMsgHeader
        {
            public static uint MsgMark = 0xaaaaaaaa;
            protected int _eMsgType = 0;
            protected int _nMsgLen = 0;        public DefaultMsgHeader()
            {
            }
            //是否需要重载,从byte[]解析出消息长度
            public DefaultMsgHeader(byte[] b)
            {
                if (b.Length >= 12)
                    _nMsgLen = BitConverter.ToInt32(b, 8);
            }
            /// <summary>消息长度</summary>
            public int Length
            {
                get { return _nMsgLen; }
                set { _nMsgLen = value; }
            }
        }    public class ExchangeMsgHeader : BaseMsgHeader
        {
            public static uint MsgMark = 0xAAAAAAAA;
            protected int m_nTotalLen = 0; //消息总长度(含消息头及消息体)
            protected int m_nCommandId = 0;//命令或响应类型
            protected int m_nSeqId = 0;    //消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)
            public ExchangeMsgHeader()
            {
            }
            //是否需要重载,从byte[]解析出消息长度
            public ExchangeMsgHeader(byte[] b)
            {
                if (b.Length >= 16)
                    m_nTotalLen = BitConverter.ToInt32(b, 4);
            }
            /// <summary>消息长度</summary>
            public int Length
            {
                get { return m_nTotalLen; }
                set { m_nTotalLen = value; }
            }
        }    #endregion