码迷,mamicode.com
首页 > Windows程序 > 详细

C#与其他系统通信接口总结

时间:2016-01-11 18:03:31      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

  大家应该都知道,在与其他系统交互的时候,通常有两种方式,webservice和socket通信。

  这个接口项目我使用的是socket通信方式,内容以xml方式包装,按照约定的格式收发。socket通信一般用到的为TCP和UDP两种,具体区别以及它们的优缺点可以参考资料http://jingyan.baidu.com/article/6dad5075df3452a123e36ecb.html,这里我采用TCP方式。

  在C#中可以使用.net提供的TcpListener建立服务端,TcpClient建立客户端。正常情况,因为TCP是全双工,只要作为服务端或者客户端连接上就可以收发信息。但是这个项目中由于第三方系统历史遗留的问题,我们同时建立了服务端和客户端,服务端用来收消息,客户端用来发消息。

  背景介绍完毕,下面上代码

  服务端代码

  

 /// <summary>
    /// 服务端类,用于接收客户端消息
    /// </summary>
    class TcpListen
    {
        /// <summary>
        /// 连接上的客户端集合 
        /// </summary>
        List<RemoteClient> remoteClientList = new List<RemoteClient>();      
        /// <summary>
        /// 服务端监听对象
        /// </summary>
        private TcpListener myListener;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="localIP"></param>
        /// <param name="port"></param>
        public TcpListen(string localIP,int port)
        {
            /// <summary>使用的本机IP地址</summary>
            IPAddress localAddress = IPAddress.Parse(localIP); 
            myListener = new TcpListener(localAddress, port);
            myListener.Start();
            //创建一个线程监听客户端连接请求
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
        }

        /// <summary>
        /// 接收客户端连接
        /// </summary>
        private void ListenClientConnect()
        {          
            while (true)
            {
                TcpClient newClient = null;
                try
                {
                    newClient = myListener.AcceptTcpClient();
                }
                catch
                {
                    //当退出时AcceptTcpClient()会产生异常
                    //因此可以利用此异常退出循环
                    break;
                }
                //每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息
                RemoteClient user = new RemoteClient(newClient);
                remoteClientList.Add(user);
                Thread threadReceive = new Thread(ReceiveData);
                threadReceive.Start(user);
                
            }
        }       

        /// <summary>
        /// 处理接收的客户端数据
        /// </summary>
        /// <param name="userState">客户端信息</param>
        private void ReceiveData(object userState)
        {
            RemoteClient user = userState as RemoteClient;
            TcpClient client = user.client;
            while (true)
            {
                byte[] BytesLenth = null;
                byte[] BytesContent = null;
                try
                {
                    if (user == null || user.br == null || user.client.Connected == false)
                    {
                        break;
                    }
                    BytesLenth = user.br.ReadBytes(2);
                    int lenth = BitConverter.ToInt16(BytesLenth, 0);
                    BytesContent = user.br.ReadBytes(lenth - 2);
                    string conContent = Encoding.Default.GetString(BytesContent);
                   
                    //如果收到是心跳信息
                    if (conContent == "0000")
                    {
                         ClassVar.frmMain.timeSpan = 0;                         
                    }
                    //如果是警情信息则加入到消息队列
                    else
                    {
                        lock (ClassVar.frmMain.lockQue)
                        {
                            ClassVar.frmMain.queueXml.Enqueue(conContent);                            
                        }
                    }
                }
                catch (Exception ex)
                {
                    RemoveUser(user);
                }
            }
        }

        /// <summary>移除用户</summary>
        /// <param name="user">指定要删除的用户</param>
        private void RemoveUser(RemoteClient remoteClient)
        {
            remoteClientList.Remove(remoteClient);
            remoteClient.Close();            
        }
   /// <summary>
    /// 服务端管理远程客户端类
    /// </summary>
    class RemoteClient
    {
        public TcpClient client{get; private set;}
        public BinaryReader br{get; private set;}
        public BinaryWriter bw{get; private set;}
        public string userName {get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="client"></param>
        public RemoteClient(TcpClient client)
        {           
            this.client = client;
            NetworkStream networkStream = client.GetStream();
            br = new BinaryReader(networkStream);
            bw = new BinaryWriter(networkStream);
            this.userName = (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString() + ":"+(client.Client.RemoteEndPoint as IPEndPoint).Port.ToString();
        }
        /// <summary>
        /// 关闭与远程客户端的连接
        /// </summary>
        public void Close()
        {
            br.Close();
            bw.Close();
            client.Close();
        }
    }

客户端

/// <summary>
    /// 客户端类,用来给服务端发送消息
    /// </summary>
    class Client
    {
        #region 变量
        /// <summary>
        /// tcp通信对象
        /// </summary>
        private TcpClient tcpClient;
        /// <summary>
        /// tcp通信中读取数据的对象
        /// </summary>
        private BinaryReader br;
        /// <summary>
        /// tcp通信中写数据的对象
        /// </summary>
        private BinaryWriter bw;
        /// <summary>
        /// 通信的远程服务器ip
        /// </summary>
        private string IP;
        /// <summary>
        /// 通信的远程服务器端口
        /// </summary>
        private int port;

      
        #endregion

        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ip">服务器IP</param>
        /// <param name="port">服务器开放的通信端口号</param>
        public Client(string ip,int port)
        {
            this.IP = ip;
            this.port = port;
        }
        #endregion

        // 连接服务器
        /// <summary>
        /// 连接服务器
        /// </summary>
        public void Connect()
        {
            try
            {
                tcpClient = new TcpClient(IP, port);
                //获取网络流
                NetworkStream networkStream = tcpClient.GetStream();
                //将网络流作为二进制读写对象
                br = new BinaryReader(networkStream);
                bw = new BinaryWriter(networkStream);
            }
            catch (Exception ex)
            {
                ClassVar.WriteErrorLog("连接服务器出错:" + Environment.NewLine + "Connect" + ex.ToString());
            }

            //后台心跳消息线程
            Thread threadHeart = new Thread(new ThreadStart(SendHeart));
            threadHeart.IsBackground = true;
            threadHeart.Start();
        }

        // 重连服务器
        /// <summary>
        /// 重连
        /// </summary>
        public void Reconnect()
        {
            try
            {
                if (tcpClient!=null)
                {
                    tcpClient.Close();
                }              
                tcpClient = new TcpClient(IP, port);
                //获取网络流
                NetworkStream networkStream = tcpClient.GetStream();
                //将网络流作为二进制读写对象
                br = new BinaryReader(networkStream);
                bw = new BinaryWriter(networkStream);
            }
            catch(Exception ex)
            {
                ClassVar.WriteErrorLog("重连服务器出错:" + Environment.NewLine + "Reconnect" + ex.ToString());
            }
        }

      

        // 给服务器的心跳,10秒一次
        /// <summary>
        /// 心跳,10秒一次
        /// </summary>
        private void SendHeart()
        {
            while (true)
            {
                Thread.Sleep(10000);
                SendMsg("0000");
            }
        }
        
        // 发送消息到服务器的方法,带发送长度
        /// <summary>
        /// 发送消息到服务器的方法,带发送长度
        /// </summary>
        /// <param name="msg">消息内容</param>
        public void SendMsg(string msgs)
        {
            try
            {
                //消息中前两个字节表示发送的消息长度
                byte[] msg = Encoding.UTF8.GetBytes(msgs);
                int length = msg.Length;
                short lengthall = (short)(length + 2);
                byte[] lengthByte = System.BitConverter.GetBytes(lengthall);
                byte[] all = lengthByte.Concat(msg).ToArray();
                //然后将字节数组写入网络流
                if (bw != null && tcpClient.Connected==true)
                {
                        bw.Write(all);
                        bw.Flush();
                        if (msgs == "0000")//心跳写单独的文件
                        {
                            ClassVar.WriteLogCommonXT(Environment.NewLine + "成功给系统发送数据:" + msgs);
                        }
                        else
                        {
                            ClassVar.WriteLogCommon(Environment.NewLine + "成功给系统发送数据:" + msgs);
                        }
                }
                else
                {
                    this.Reconnect();
                }
            }
            catch (Exception ex)
            {
                ClassVar.WriteErrorLog("发送消息到服务器出错:" + Environment.NewLine + "SendMsg" + ex.ToString());
            }
        }

        // 发送消息到服务器的方法,老方法,不带长度
        /// <summary>
        /// 发送消息到服务器的方法,老方法,不带长度
        /// </summary>
        /// <param name="msg">消息内容</param>
        public void SendOldMsg(string msg)
        {
                byte[] sendMsg = Encoding.UTF8.GetBytes(msg);
                //然后将字节数组写入网络流
                bw.Write(sendMsg);
                bw.Flush();           
        }
      
        // 将无符号32位整数转换为长度为2的字节数组,大端对齐
        /// <summary>
        /// 将无符号32位整数转换为长度为2的字节数组,大端对齐
        /// </summary>
        /// <param name="value">无符号32位整数</param>
        /// <returns>长度为2的字节数组</returns>
        public byte[] ToBytesArray(int value)
        {
            byte[] buffer = new byte[2];
            for (int i = 1; i >= 0; i--)
            {
                buffer[i] = (byte)(0x000000ff & value);
                value = value >> 8;
            }
            byte temp = buffer[0];
            buffer[0] = buffer[1];
            buffer[1] = temp;
            return buffer;
        }
    }

界面调用方法

 /// <summary>
        /// 本地客户端对象
        /// </summary>
        Client client;
        /// <summary>
        /// 第三方服务器IP地址
        /// </summary>
        string _ServerIP;
        /// <summary>
        /// 第三方服务器端口
        /// </summary>
        int _ServerPort;
        /// <summary>
        /// 第三方系统服务器给本机发送的心跳计时锁对象
        /// </summary>
        public object objTimeSpan = new object();
        /// <summary>
        /// 第三方系统服务器给本机发送的心跳计时
        /// </summary>
        public int timeSpan = 0;
        /// <summary>
        /// 第三方系统服务器发送过来的消息队列锁对象
        /// </summary>
        public object lockQue = new object();
        /// <summary>
        /// 第三方系统服务器发送过来的消息队列
        /// </summary>
        public Queue<string> queueXml = new Queue<string>();

        // 初始化数据
        /// <summary>
        /// 初始化数据
        /// </summary>
        private void Ini()
        {          
            //获取本机IPv4地址
            string localIPAddr = GetLocalIP();
            client = new Client(_ServerIP, _ServerPort);
            //连接第三方系统服务器,只用于发送消息用,发送心跳线程
            client.Connect();
            //与第三方系统服务器重连判断线程
            Thread threadChenck = new Thread(new ThreadStart(CheckHeart));
            threadChenck.IsBackground = true;
            threadChenck.Start();
            //启动监听服务器,用于接收发送发送的消息
            TcpListen _TcpListen = new TcpListen(localIPAddr, 11118);
            Thread threadRead = new Thread(ReadQueThread);
            threadRead.IsBackground = true;
            threadRead.Start();
        }

        // 获取本机IPv4地址
        /// <summary>
        /// 获取本机IPv4地址
        /// </summary>
        /// <returns></returns>
        public static string GetLocalIP()
        {
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    //从IP地址列表中筛选出IPv4类型的IP地址
                    //AddressFamily.InterNetwork表示此IP为IPv4,
                    //AddressFamily.InterNetworkV6表示此地址为IPv6类型
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        return IpEntry.AddressList[i].ToString();
                    }
                }
                return "127.0.0.1";
            }
            catch (Exception ex)
            {
                return "127.0.0.1";
            }
        }

        // 与第三方系统重连判断
        /// <summary>
        /// 与第三方系统重连判断
        /// </summary>
        private void CheckHeart()
        {
            while (true)
            {
                Thread.Sleep(3000);
                lock (objTimeSpan)
                {
                    timeSpan = timeSpan + 2;
                }
                if (timeSpan >= maxTime)
                {
                    client.Reconnect();
                    timeSpan = 0;
                }
            }
        }

        //读取第三方系统消息队列,处理后发送到协同
        /// <summary>
        /// 读取第三方系统消息队列,处理后发送到协同
        /// </summary>
        private void ReadQueThread()
        {
            while (true)
            {
                try
                {
                    if (queueXml.Count > 0)
                    {
                        lock (lockQue)
                        {
                            string xml = queueXml.Dequeue();
                            //本地处理
                            FToLocal(xml);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ClassVar.WriteErrorLog("方法ReadQueThread出错,详细信息:" + ex.ToString());
                }
                Thread.Sleep(5);
            }
        } 

 

C#与其他系统通信接口总结

标签:

原文地址:http://www.cnblogs.com/KQNLL/p/5121962.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!