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

实现Winform与Sliverlight之间的Socket通信转换

时间:2015-05-08 13:10:24      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:sliverlight   winform   socket   c#   

众所周知,Winform下的Socket与Sliverlight的Socket是不可以直接通信的,原因请参考http://www.cnblogs.com/ZetaChow/archive/2009/05/16/2237347.html以下是经本人验证过的转换方法,具体流程为:先建立一个winform client端接收已存在的winform server端发来的信息,将接收到的信息通过新建的sliverlight server端发出,再建立一个sliverlight client端接收此消息,如此一来便也达到了用sliverlight接收winform消息的效果。代码如下:

1.建立winform client

        #region 接收来自源Server的客户端

        Dictionary<string, ConnClientHelp> dictConn = new Dictionary<string, ConnClientHelp>();
        Socket socketClient = null;
        Thread threadClient = null;
        public void Client()
        {
            try
            {
                socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ipaddress = GetIP("192.168.0.3");
                IPEndPoint endpoint = new IPEndPoint(ipaddress, 8889);
                socketClient.Connect(endpoint);
                threadClient = new Thread(RecMsg);
                threadClient.IsBackground = true;
                threadClient.Start();
            }
            catch (Exception ex)
            { }
        }


        /// <summary>
        /// 接收服务端发来信息的方法
        /// </summary>
        private void RecMsg()
        {
            while (true) //持续监听服务端发来的消息
            {
                try
                {
                    byte[] arrRecMsg = new byte[1024 * 1024 * 10];
                    length = socketClient.Receive(arrRecMsg);
                    strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                     foreach (ConnClientHelp conn in dictConn.Values)
                     {
                          conn.Send(strRecMsg, conn);
                     }
                }
                catch (Exception eee)
                { }
            }
        }
        #endregion

2.建立sliverlight server

        #region 向Sliverlight发送的服务端
        Thread threadServer = null; //负责监听客户端的线程
        Socket socketServer = null; //负责监听客户端的套接字

        Socket socConnection;//创建一个负责和客户端通信的套接字
       
        public void Server()
        {
            try
            {
                //定义一个套接字用于监听客户端发来的信息  包含3个参数(IP4寻址协议,流式连接,TCP协议)
                socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //服务端发送信息 需要1个IP地址和端口号
                IPAddress ipaddress = IPAddress.Parse("192.168.2.103");
                //将IP地址和端口号绑定到网络节点endpoint上
                IPEndPoint endpoint = new IPEndPoint(ipaddress, 4530);
                //监听绑定的网络节点
                socketServer.Bind(endpoint);
                //将套接字的监听队列长度限制为40
                socketServer.Listen(40);
                //创建一个监听线程
                threadServer = new Thread(WatchConnecting);
                //将窗体线程设置为与后台同步
                threadServer.IsBackground = true;
                //启动线程
                threadServer.Start();
            }
            catch (Exception mmm)
            { }
        }

        /// <summary>
        /// 监听客户端发来的请求
        /// </summary>
        private void WatchConnecting()
        {
            while (true)  //持续不断监听客户端发来的请求
            {
                try
                {
                    socConnection = socketServer.Accept();
                    //创建一个通信线程
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg);
                    Thread thr = new Thread(pts);
                    thr.IsBackground = true;
                    //启动线程
                    thr.Start(socConnection);

                    ConnClientHelp connection = new ConnClientHelp(socConnection);
                    //将负责与当前连接请求客户端 通信的套接字所在的连接通信类 对象 装入集合
                    dictConn.Add(socConnection.RemoteEndPoint.ToString(), connection);
                }
                catch (Exception ex)
                { }
            }
        }

        /// <summary>
        /// 发送信息到客户端的方法
        /// </summary>
        /// <param name="sendMsg">发送的字符串信息</param>
        private void ServerSendMsg(string sendMsg)
        {
            //将输入的字符串转换成 机器可以识别的字节数组
            byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //向客户端发送字节数组信息
            socConnection.Send(arrSendMsg);
        }

        /// <summary>
        /// 接收客户端发来的信息
        /// </summary>
        /// <param name="socketClientPara">客户端套接字对象</param>
        private void ServerRecMsg(object socketClientPara)
        {
            try
            {
                Socket socketServer = socketClientPara as Socket;
                if (true)
                {
                    //创建一个内存缓冲区 其大小为1024*1024字节  即1M
                    byte[] arrServerRecMsg = new byte[1024 * 1024];
                    //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
                    int length = socketServer.Receive(arrServerRecMsg);
                    //将机器接受到的字节数组转换为人可以读懂的字符串
                    string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
                }
            }
            catch (Exception ee)
            { }
        }
        #endregion

3.建立sliverlight client

        #region 客户端,将接收到的数据发送至地图
        private Socket socket;
        private void ConnectSocket()
        {
            DnsEndPoint hostEntry = new DnsEndPoint("192.168.2.103", 4530);//建立终结点对象
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket对象
            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();//创建Socket异步事件参数
            byte[] buffer = Encoding.UTF8.GetBytes("Start");//将消息转化为发送的byte[]格式
            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(socketArgs_Completed);//注册Socket完成事件
            socketEventArg.RemoteEndPoint = hostEntry;//设置Socket异步事件远程终结点
            socketEventArg.UserToken = buffer;//将定义好的Socket对象赋值给Socket异步事件参数的运行实例属性
            try
            {
                socket.ConnectAsync(socketEventArg);
            }
            catch (SocketException ex)
            {
                throw new SocketException((int)ex.ErrorCode);
            }
        }
        private void socketArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            //检查是否发送出错
            if (e.SocketError != SocketError.Success)
            {
                if (e.SocketError == SocketError.ConnectionAborted){Dispatcher.BeginInvoke(() => MessageBox.Show("连接超时....请重试!"));}
                else if (e.SocketError == SocketError.ConnectionRefused){Dispatcher.BeginInvoke(() => MessageBox.Show("无法连接到服务器端:" + e.SocketError));}
                else {Dispatcher.BeginInvoke(() => MessageBox.Show(e.SocketError.ToString())); }

                return;
            }

            if (e.LastOperation == SocketAsyncOperation.Connect)
            {
                //客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求
                byte[] userbytes = (byte[])e.UserToken;
                e.SetBuffer(userbytes, 0, userbytes.Length);
                socket.SendAsync(e);
            }
            else if (e.LastOperation == SocketAsyncOperation.Send)
            {
                //客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息
                byte[] userbytes = new byte[1024 * 1024];
                e.SetBuffer(userbytes, 0, userbytes.Length);
                socket.ReceiveAsync(e);
            }
            else if (e.LastOperation == SocketAsyncOperation.Receive)
            {
                byte[] userbytes = new byte[1024 * 1024];
                //客户端步骤四:获取到服务器返回的消息
                string RecevieStr = Encoding.UTF8.GetString(e.Buffer, 0, e.Buffer.Length).Replace("\0", "");
                Dispatcher.BeginInvoke(() => { MessageBox.Show(RecevieStr); });
        }
        #endregion

4.用到的三个help文件

(1)clientaccesspolicy.xml

<?xml version="1.0" encoding="UTF-8"?>
 -<access-policy>
    -<cross-domain-access>
        -<policy>
            -<allow-from>
                 <domain uri="*"/>
            </allow-from>
            -<grant-to>
                  <socket-resource protocol="tcp" port="4502-4534"/>
            </grant-to>
        </policy>
    </cross-domain-access>
</access-policy>

(2)program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace TransClientServer
{
    static class Program
    {
        static void Main(string[] args)
        {
            //策略步骤一:启动监听943端口是否有需要安全策略文件请求
            Thread access = new Thread(new ThreadStart(accessThread));
            access.Start();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new transForm());
        }
        //策略请求监听
        static void accessThread()
        {
            //获取943端口监听的Socket服务端
            Socket socket = GetSocketServer(943);
            while (true)
            {
                Socket new_access = socket.Accept();
                string clientPolicyString = "<policy-file-request/>";
                byte[] requestbytes = new byte[clientPolicyString.Length];
                new_access.Receive(requestbytes);
                string requeststring = System.Text.Encoding.UTF8.GetString(requestbytes, 0, requestbytes.Length);

                if (requeststring == clientPolicyString)
                {
                    //策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端
                    byte[] accessbytes = GetPolicyToClient();
                    new_access.Send(accessbytes, accessbytes.Length, SocketFlags.None);
                    new_access.Close();
                }
                Thread.Sleep(100);
            }
        }

        //根据端口建立Socket服务器端
        static Socket GetSocketServer(int serverPort)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(new IPEndPoint(IPAddress.Any, serverPort));
            socket.Listen(40);
            return socket;
        }

        //获取安全策略文件的byte[]
        static byte[] GetPolicyToClient()
        {
            string path = Environment.CurrentDirectory.Replace("\\bin\\Debug", "");
            FileStream fs = new FileStream(path + @"\clientaccesspolicy.xml", FileMode.Open);
            int length = (int)fs.Length;
            byte[] bytes = new byte[length];
            fs.Read(bytes, 0, length);
            fs.Close();
            return bytes;
        }
    }
}


(3)ConnClientHelp.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace TransClientServer.Help
{
    /// <summary>
    /// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字,和线程)
    /// </summary>
    class ConnClientHelp
    {
        Socket sokMsg;
        Thread threadMsg;

        #region 构造函数
        /// <summary>
        ///
        /// </summary>
        /// <param name="sokMsg">通信套接字</param>
        public ConnClientHelp(Socket sokMsg)
        {
            this.sokMsg = sokMsg;

            this.threadMsg = new Thread(RecMsg);
            this.threadMsg.IsBackground = true;
            this.threadMsg.Start();
        }
        #endregion

        bool isRec = true;
        #region 02负责监听客户端发送来的消息
        void RecMsg()
        {
            while (isRec)
            {
                try
                {
                    byte[] arrMsg = new byte[1024 * 1024 * 10];
                    //接收 对应 客户端发来的消息
                    int length = sokMsg.Receive(arrMsg);
                    //将接收到的消息数组里真实消息转成字符串
                    string strMsg = System.Text.Encoding.UTF8.GetString(arrMsg, 0, length);
                }
                catch (Exception ex)
                {
                    
                }
            }
        }
        #endregion

        #region 03向客户端发送消息
        /// <summary>
        /// 向客户端发送消息
        /// </summary>
        /// <param name="strMsg"></param>
        public void Send(string strMsg, ConnClientHelp conn)
        {
            try
            {
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                byte[] arrMsgFinal = new byte[arrMsg.Length + 1];

                arrMsgFinal[0] = 0;//设置 数据标识位等于0,代表 发送的是 文字
                arrMsg.CopyTo(arrMsgFinal, 1);

                sokMsg.Send(arrMsgFinal);
            }
            catch (Exception ex)
            {
                if ("远程主机强迫关闭了一个现有的连接。".Equals(ex.Message))
                {
                    conn.CloseConnection();
                }
            }
        }
        #endregion


        #region 04关闭与客户端连接
        /// <summary>
        /// 关闭与客户端连接
        /// </summary>
        public void CloseConnection()
        {
            threadMsg.Interrupt();
            isRec = false;
        }
        #endregion
    }
}



转载/引用请注明出处,谢谢!

实现Winform与Sliverlight之间的Socket通信转换

标签:sliverlight   winform   socket   c#   

原文地址:http://blog.csdn.net/yss19900512/article/details/45576771

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