使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图。下面就来看看本文实现的功能: Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发回的新的坐标,并在地图相应的位置进行标识。
原文: 使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图。下面就来看看本文实现的功能:

Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发回的新的坐标,并在地图相应的位置进行标识。最后在地图上我们就会看到一个自动绘制的三角函数曲线。

关于本文的一点说明:

1.由于时间和篇幅的关系,也由于本人能力有限,所以程序还存在很多bug,不够完善,也许你运行的时候还会抛异常,本文关注的是关键功能的实现,所以希望高手勿喷,如果您有更好的方法和建议欢迎留言分享。

2.作者没有GPS设置,相信大多数也是一样,所以无法实际的模拟从GPS获取数据,在地图上展示,因此本文模拟在服务器动态实时的生成坐标数据,并实时发送给客户端。不过如果您有GPS设备,实际上实现的过程是一样。

3.本文的坐标数据是自己写的一个三角函数,所以最后在地图上实时绘制的运动轨迹也是一个三角函数,当然也可以换成其他任意的轨迹,只要可以写出其坐标生成函数即可。

4.本文的具体过程是客户端向服务器发送一个起始的坐标,当然也可以是其他的信息,只不过便于绘制和理解,所以用了一个坐标,服务器接收该坐标,并基于该坐标生成新的坐标数据。不过在实际的GPS中,只需要客户端发送位置请求,服务器将真实的GPS坐标数据发送给客户端即可。

5.本文的服务器端部分代码来自于该博主的博文:

http://www.cnblogs.com/webabcd/archive/2008/12/22/1359551.html

在此感谢webabcd(王磊 MVP)的分享。

下面就来看看具体实现的过程。

一.服务器端

在上一篇中说到了与服务器通信,大致上的过程是客户端发送一个信息,服务器接收客户端信息,服务器回复一条信息,客户端接收服务器信息。但在本文中,稍微有些不一样。

在本文中,客户端发送位置请求(本文客户端发送一个用于构造新坐标的起始坐标点),然后服务器基于接收的起始坐标,实时的生成新的坐标数据,并不断的往客户端发送,客户端不断接受服务器发送来的新数据,并在地图上标示。所以这里不像之前客户端请求一次,服务器则回复一条信息。

 下面给出具体的代码I(可以参看上面给出链接的博文):

 服务器端界面如下:

具体过程:

  1.1 启动策略文件服务

 #region Start The Policy Server 验证策略文件
            PolicySocketServer StartPolicyServer = new PolicySocketServer();
            Thread th = new Thread(new ThreadStart(StartPolicyServer.StartSocketServer));
            th.IsBackground = true;
            th.Start();
            #endregion
PolicySocketServer 类在上一篇文章中给出:
http://www.cnblogs.com/potential/archive/2013/01/23/2873035.html
1.2 启动服务器端Socket服务,监听端口,连接Socket。
1.2.1 声明类级别的变量
 //客户端传入的起始坐标
        private double startx = 0;
        private double starty = 0;
        //服务器端生成的新坐标
        private double X;
        private double Y;
        //判断是否成功接收服务器发来的新的坐标
        bool receivedCoor = false;
        //够找新坐标时的步长
        private double step = 0;
1.2.2启动Socket服务,开始连接
    private void StartupSocketServer()
        {
            //定时器,每0.3秒运行一次指定的方法
            //这里可自己手动修改刷新数据的时间
            _timer = new System.Timers.Timer();
            _timer.Interval = 300;
            _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
            _timer.Start();

            //初始化Socket
            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //创建终结点,获取当前主机IP
            IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
            IPEndPoint localEndPoint = new IPEndPoint(ipHost.AddressList[3], 4530);
            //Win7 启动了IPV6地址,所以是3,如果为XP系统可换成0,1再试试
            _syncContext.Post(ChangeIPText, ipHost.AddressList[3].ToString());
            //绑定端口
            _listener.Bind(localEndPoint);
            _listener.Listen(100);

            while (true)
            {
                //重置ManualResetEvent,由线程来控制ManualResetEvent
                _connectDone.Reset();

                _listener.BeginAccept(new AsyncCallback(OnClientConnect), null);

                _connectDone.WaitOne();
            }
        }
private void OnClientConnect(IAsyncResult result)
        {
            _connectDone.Set();
            ClientSocketPacket client = new ClientSocketPacket();
            client.Socket = _listener.EndAccept(result);
            _clientList.Add(client);
            _syncContext.Post(ResultCallback, "客户端已经连接");

            try
            {
                client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);
            }
            catch (SocketException ex)
            {
                HandleException(client, ex);
            }
        }

1.3 接收数据

  private void OnDataReceived(IAsyncResult result)
        {
            ClientSocketPacket client = result.AsyncState as ClientSocketPacket;
            int count = 0;
            try
            {
                if (client.Socket.Connected)
                    count = client.Socket.EndReceive(result);
            }
            catch (SocketException ex)
            {
                HandleException(client,ex);
            }

            foreach (byte b in client.Buffer.Take(count))
            {
                if (b == 0)
                    continue;
                client.RececivedByte.Add(b);
            }

            string receivedString = UTF8Encoding.UTF8.GetString(client.Buffer, 0, count);
            if (client.Socket.Connected && client.Socket.Available == 0 && receivedString.Contains(_endMarker))
            {
                string content = UTF8Encoding.UTF8.GetString(client.RececivedByte.ToArray());
                content = content.Replace(_endMarker, "");
                client.RececivedByte.Clear();
                SendData("服务器端已经成功接收数据!");
                _syncContext.Post(ResultCallback, "服务器在" + DateTime.Now.ToShortTimeString() + "接收数据:" + content);
            }
            //对接受的数据进行分析
            //便于简单,客户端发送的坐标字符串格式是"x|y"
            //所以这里只是简单的判断是否有‘|’标识符
            if (receivedString.Contains("|"))
            {
                string[] coordinates = receivedString.Split('|');
                startx = Convert.ToDouble(coordinates[0]);
                starty = Convert.ToDouble(coordinates[1]);
                _syncContext.Post(ChangeReceivedText, receivedString);
                step = 0;
                receivedCoor = true;
            }

            try
            {
                // 继续开始接收客户端传入的数据
                if (client.Socket.Connected)
                    client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, 0, new AsyncCallback(OnDataReceived), client);
            }
            catch (SocketException ex)
            {
                HandleException(client, ex);
            }
        }

1.5 发送数据等

 private void SendData(string data)
        {
            byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
            for (int i = 0; i < _clientList.Count;i++ )
            {

                    if (_clientList[i].Socket.Connected)
                    {
                        _clientList[i].Socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnDataSend), _clientList[i]);
                        _syncContext.Post(ResultCallback, "服务器在" + DateTime.Now.ToShortTimeString() + "发送数据:" + data);
                    }
                    else
                    {
                        _clientList[i].Socket.Close();
                        _clientList.Remove(_clientList[i]);
                    }
                }
        }

1.6 生成新坐标的方法,本文利用的只是一个简单的Sin三角函数,读者可构造自己的函数。

  private void newCoordinate(out double latitude, out double longitude, ref double step)
        {
            latitude = startx + 30 * step;

            longitude = starty + 100 * Math.Sin(step);

            step = step + 0.1;
        }

1.7 Timer定时器的触发函数,定时向调用构造新坐标的方法,构造新的坐标,并发送数据的到客户端

  private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //如果服务器成功接收客户端传入的坐标,则向服务器发送数据
            if (receivedCoor == true)
            {
                newCoordinate(out X, out Y, ref step);
                string lat = startx.ToString("#0.00");
                string lon = starty.ToString("#0.00");
                //将新的坐标发送给客户端
                SendData(string.Format("{0}|{1}", X, Y));
            }
        }

1.8 其他相关函数,用于更改UI

     private void ResultCallback(object result)
        {
            // 输出相关信息
            listBox1.Items.Add(result);
        }

        private void ChangeIPText(object str)
        {
            HostIPTextBox.Text = str.ToString();
        }
        private void ChangeReceivedText(object str)
        {
            ReceivedTextBox.Text = str.ToString();
        }

1.9 开启Socket服务Button事件,及清除消息列表

 private void StartButton_Click(object sender, EventArgs e)
        {
            // 启动后台线程去运行 Socket 服务
            Thread thread = new Thread(new ThreadStart(StartupSocketServer));
            thread.IsBackground = true;
            thread.Start();
        }

        private void ClearButton_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
        }

Main.cs

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.Threading;
 10 using System.Net.Sockets;
 11 using System.Net;
 12 using System.IO;
 13 
 14 namespace WindowsServer
 15 {
 16     public partial class Form1 : Form
 17     {
 18         SynchronizationContext _syncContext;
 19         System.Timers.Timer _timer;
 20         private string _endMarker = "^";
 21 
 22         private Socket _listener;
 23 
 24         private ManualResetEvent _connectDone = new ManualResetEvent(false);
 25         private List<ClientSocketPacket> _clientList = new List<ClientSocketPacket>();
 26 
 27         //客户端传入的起始坐标
 28         private double startx = 0;
 29         private double starty = 0;
 30         //服务器端生成的新坐标
 31         private double X;
 32         private double Y;
 33         //判断是否成功接收服务器发来的新的坐标
 34         bool receivedCoor = false;
 35         //够找新坐标时的步长
 36         private double step = 0;
 37 
 38         public Form1()
 39         {
 40             InitializeComponent();
 41             #region Start The Policy Server 验证策略文件
 42             PolicySocketServer StartPolicyServer = new PolicySocketServer();
 43             Thread th = new Thread(new ThreadStart(StartPolicyServer.StartSocketServer));
 44             th.IsBackground = true;
 45             th.Start();
 46             #endregion
 47 
 48             //UI线程
 49             _syncContext = SynchronizationContext.Current;
 50             //启动线程运行Socket服务
 51 
 52         }
 53 
 54         private void StartupSocketServer()
 55         {
 56             //定时器,每0.3秒运行一次指定的方法
 57             //这里可自己手动修改刷新数据的时间
 58             _timer = new System.Timers.Timer();
 59             _timer.Interval = 300;
 60             _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
 61             _timer.Start();
 62 
 63             //初始化Socket
 64             _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 65             //创建终结点,获取当前主机IP
 66             IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
 67             IPEndPoint localEndPoint = new IPEndPoint(ipHost.AddressList[3], 4530);
 68             //Win7 启动了IPV6地址,所以是3,如果为XP系统可换成0,1再试试
 69             _syncContext.Post(ChangeIPText, ipHost.AddressList[3].ToString());
 70             //绑定端口
 71             _listener.Bind(localEndPoint);
 72             _listener.Listen(100);
 73 
 74             while (true)
 75             {
 76                 //重置ManualResetEvent,由线程来控制ManualResetEvent
 77                 _connectDone.Reset();
 78 
 79                 _listener.BeginAccept(new AsyncCallback(OnClientConnect), null);
 80 
 81                 _connectDone.WaitOne();
 82             }
 83         }
 84 
 85         private void OnClientConnect(IAsyncResult result)
 86         {
 87             _connectDone.Set();
 88             ClientSocketPacket client = new ClientSocketPacket();
 89             client.Socket = _listener.EndAccept(result);
 90             _clientList.Add(client);
 91             _syncContext.Post(ResultCallback, "客户端已经连接");
 92 
 93             try
 94             {
 95                 client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);
 96             }
 97             catch (SocketException ex)
 98             {
 99                 HandleException(client, ex);
100             }
101         }
102 
103         private void OnDataReceived(IAsyncResult result)
104         {
105             ClientSocketPacket client = result.AsyncState as ClientSocketPacket;
106             int count = 0;
107             try
108             {
109                 if (client.Socket.Connected)
110                     count = client.Socket.EndReceive(result);
111             }
112             catch (SocketException ex)
113             {
114                 HandleException(client,ex);
115             }
116 
117             foreach (byte b in client.Buffer.Take(count))
118             {
119                 if (b == 0)
120                     continue;
121                 client.RececivedByte.Add(b);
122             }
123 
124             string receivedString = UTF8Encoding.UTF8.GetString(client.Buffer, 0, count);
125             if (client.Socket.Connected && client.Socket.Available == 0 && receivedString.Contains(_endMarker))
126             {
127                 string content = UTF8Encoding.UTF8.GetString(client.RececivedByte.ToArray());
128                 content = content.Replace(_endMarker, "");
129                 client.RececivedByte.Clear();
130                 SendData("服务器端已经成功接收数据!");
131                 _syncContext.Post(ResultCallback, "服务器在" + DateTime.Now.ToShortTimeString() + "接收数据:" + content);
132             }
133             //对接受的数据进行分析
134             //便于简单,客户端发送的坐标字符串格式是"x|y"
135             //所以这里只是简单的判断是否有‘|’标识符
136             if (receivedString.Contains("|"))
137             {
138                 string[] coordinates = receivedString.Split('|');
139                 startx = Convert.ToDouble(coordinates[0]);
140                 starty = Convert.ToDouble(coordinates[1]);
141                 _syncContext.Post(ChangeReceivedText, receivedString);
142                 step = 0;
143                 receivedCoor = true;
144             }
145 
146             try
147             {
148                 // 继续开始接收客户端传入的数据
149                 if (client.Socket.Connected)
150                     client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, 0, new AsyncCallback(OnDataReceived), client);
151             }
152             catch (SocketException ex)
153             {
154                 HandleException(client, ex);
155             }
156         }
157 
158         private void SendData(string data)
159         {
160             byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
161             for (int i = 0; i < _clientList.Count;i++ )
162             {
163 
164                     if (_clientList[i].Socket.Connected)
165                     {
166                         _clientList[i].Socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnDataSend), _clientList[i]);
167                         _syncContext.Post(ResultCallback, "服务器在" + DateTime.Now.ToShortTimeString() + "发送数据:" + data);
168                     }
169                     else
170                     {
171                         _clientList[i].Socket.Close();
172                         _clientList.Remove(_clientList[i]);
173                     }
174                 }
175         }
176 
177         private void OnDataSend(IAsyncResult result)
178         {
179             ClientSocketPacket client = result.AsyncState as ClientSocketPacket;
180             try
181             {
182                 if (client.Socket.Connected)
183                     client.Socket.EndSend(result);
184             }
185             catch (SocketException ex)
186             {
187                 HandleException(client, ex);
188             }
189         }
190 
191         private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
192         {
193             //如果服务器成功接收客户端传入的坐标
194             if (receivedCoor == true)
195             {
196                 newCoordinate(out X, out Y, ref step);
197                 string lat = startx.ToString("#0.00");
198                 string lon = starty.ToString("#0.00");
199                 //将新的坐标发送给客户端
200                 SendData(string.Format("{0}|{1}", X, Y));
201             }
202         }
203 
204         private void newCoordinate(out double latitude, out double longitude, ref double step)
205         {
206             latitude = startx + 30 * step;
207 
208             longitude = starty + 100 * Math.Sin(step);
209 
210             step = step + 0.1;
211         }
212 
213         private void HandleException(ClientSocketPacket client, SocketException ex)
214         {
215             if (client.Socket == null)
216                 return;
217             // 在服务端记录异常信息,关闭导致异常的 Socket,并将其清除出客户端 Socket 列表
218             _syncContext.Post(ResultCallback, client.Socket.RemoteEndPoint.ToString() + " - " + ex.Message);
219             client.Socket.Close();
220             _clientList.Remove(client);
221         }
222 
223         private void ResultCallback(object result)
224         {
225             // 输出相关信息
226             listBox1.Items.Add(result);
227         }
228 
229         private void ChangeIPText(object str)
230         {
231             HostIPTextBox.Text = str.ToString();
232         }
233         private void ChangeReceivedText(object str)
234         {
235             ReceivedTextBox.Text = str.ToString();
236         }
237         private void StartButton_Click(object sender, EventArgs e)
238         {
239             // 启动后台线程去运行 Socket 服务
240             Thread thread = new Thread(new ThreadStart(StartupSocketServer));
241             thread.IsBackground = true;
242             thread.Start();
243         }
244 
245         private void StopButton_Click(object sender, EventArgs e)
246         {
247             listBox1.Items.Clear();
248         }
249     }
250 }

二、Silverlight客户端

UI界面如下:



客户端实现的过程和上一篇文章差不多,代码几乎没有变化,只不过是连续的想服务器获取数据,代码如下:
  private void socketEventArg_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("Socket连接已断开!"));
                }
                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)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    listBox1.Items.Add("客户端在" + DateTime.Now.ToShortTimeString() + ",发送消息:" + MessageTextBox.Text);
                });
                byte[] userbytes = new byte[1024];
                e.SetBuffer(userbytes, 0, userbytes.Length);
                socket.ReceiveAsync(e);
            }//接收服务器数据
            else if (e.LastOperation == SocketAsyncOperation.Receive)
            {
                string RecevieStr = Encoding.UTF8.GetString(e.Buffer, 0, e.Buffer.Length).Replace("\0", "");
                Dispatcher.BeginInvoke(() =>
                {
                    listBox1.Items.Add("服务器在" + DateTime.Now.ToShortTimeString() + ",回复消息:" + RecevieStr);
                });
               //分析服务器发送回来的坐标数据,数据格式“x|y”
                if (RecevieStr.Contains("|"))
                {
                    string[] coor = RecevieStr.Split('|');
                    //构造新的坐标点
                    MapPoint mp1 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
                    x = coor[0];
                    y = coor[1];
                    MapPoint mp2 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
                    //在地图中绘制点和轨迹
                    Dispatcher.BeginInvoke(() => { CreatPoint(mp2); });
                    Dispatcher.BeginInvoke(() => { CreatLine(mp1, mp2);});
                }
              //继续向服务器接收数据,注意不要关闭Socket连接
                socket.ReceiveAsync(e); 
            }
        }

在地图上添加点和线的方法

    private void CreatPoint(MapPoint mp)
       {
           Graphic g = new Graphic()
           {
               Symbol = new SimpleMarkerSymbol()
               {
                   Size = 18,
                   Color = new SolidColorBrush(Colors.Blue),
                   Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
               },
               Geometry = mp
           };
           graphiclayer.Graphics.Clear();
           graphiclayer.Graphics.Add(g);
       }

       private void CreatLine(MapPoint mp1,MapPoint mp2)
       {
           ESRI.ArcGIS.Client.Geometry.Polyline pl = new ESRI.ArcGIS.Client.Geometry.Polyline();
           ESRI.ArcGIS.Client.Geometry.PointCollection pc = new ESRI.ArcGIS.Client.Geometry.PointCollection();
           pc.Add(mp1);
           pc.Add(mp2);
           pl.Paths.Add(pc);
           Graphic g = new Graphic()
           {
               Symbol=LayoutRoot.Resources["LineSymbol"] as SimpleLineSymbol,
               Geometry = pl
           };
           routeLayer.Graphics.Add(g);
       }

本文通过双击地图获得一个起始点坐标,并将该坐标发送给服务器,示例代码:

  private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
            MapPoint mp = e.MapPoint;
            x = mp.X.ToString ("#0.00");
            y = mp.Y.ToString ("#0.00");
            Graphic g = new Graphic()
            {
                Symbol = new SimpleMarkerSymbol()
                {
                    Size=9,
                    Color=new SolidColorBrush(Colors.Blue),
                    Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
                },
                Geometry=mp
            };
            graphiclayer.Graphics.Add(g);
            MessageTextBox.Text = x + "|" + y;
        }

关于其他部分的代码,例如声明图层,情况列表再次不再强调,具体请看下面代码:

MainPage.cs

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Net;
  5 using System.Windows;
  6 using System.Windows.Controls;
  7 using System.Windows.Documents;
  8 using System.Windows.Input;
  9 using System.Windows.Media;
 10 using System.Windows.Media.Animation;
 11 using System.Windows.Shapes;
 12 using System.Net.Sockets;
 13 using System.Text;
 14 using ESRI.ArcGIS.Client;
 15 using ESRI.ArcGIS.Client.Geometry;
 16 using ESRI.ArcGIS.Client.Symbols;
 17 using ESRI.ArcGIS.Client.Tasks;
 18 namespace SilverlightSocket
 19 {
 20     public partial class MainPage : UserControl
 21     {
 22         private Socket socket;
 23         private string x, y;
 24         GraphicsLayer graphiclayer;
 25         GraphicsLayer routeLayer;
 26         public MainPage()
 27         {
 28             InitializeComponent();
 29             SendButton.Click += new RoutedEventHandler(SendButton_Click);
 30             ClearButton.Click += ClearButton_Click;
 31             MyMap.MouseClick+=MyMap_MouseClick;
 32             graphiclayer = MyMap.Layers["GraphicLayer"] as GraphicsLayer;
 33             routeLayer = MyMap.Layers["routeLayer"] as GraphicsLayer;
 34         }
 35 
 36         private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
 37         {
 38             MapPoint mp = e.MapPoint;
 39             x = mp.X.ToString ("#0.00");
 40             y = mp.Y.ToString ("#0.00");
 41             Graphic g = new Graphic()
 42             {
 43                 Symbol = new SimpleMarkerSymbol()
 44                 {
 45                     Size=9,
 46                     Color=new SolidColorBrush(Colors.Blue),
 47                     Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
 48                 },
 49                 Geometry=mp
 50             };
 51             graphiclayer.Graphics.Add(g);
 52             MessageTextBox.Text = x + "|" + y;
 53         }
 54 
 55         void ClearButton_Click(object sender, RoutedEventArgs e)
 56         {
 57             listBox1.Items.Clear();
 58         }
 59 
 60         private void SendButton_Click(object sender, RoutedEventArgs e)
 61         {
 62             if(string.IsNullOrEmpty(IPTextBox.Text)||string.IsNullOrEmpty(PortTextBox.Text))
 63             {
 64                 MessageBox.Show ("请输入主机IP地址和端口号!");
 65                 return;
 66             }
 67             //ip地址
 68             string host=IPTextBox.Text.Trim();
 69             //端口号
 70             int port=Convert.ToInt32(PortTextBox.Text.Trim());
 71             //建立终结点对象
 72             DnsEndPoint hostEntry=new DnsEndPoint(host,port);
 73             //创建一个Socket对象
 74             socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
 75             //创建Socket异步事件参数
 76             SocketAsyncEventArgs socketEventArg=new SocketAsyncEventArgs ();
 77             //将消息转化为发送的byte[]格式
 78             byte[]buffer=Encoding.UTF8.GetBytes(MessageTextBox.Text);
 79             //注册Socket完成事件
 80             socketEventArg.Completed+=new EventHandler<SocketAsyncEventArgs>(socketEventArg_Completed);
 81             //设置Socket异步事件远程终结点
 82             socketEventArg.RemoteEndPoint=hostEntry;
 83             //将定义好的Socket对象赋值给Socket异步事件参数的运行实例属性
 84             socketEventArg.UserToken = buffer;
 85             //socketEventArg.UserToken = socket;
 86             try
 87             {
 88                 socket.ConnectAsync(socketEventArg);
 89             }
 90             catch(SocketException ex)
 91             {
 92                 throw new SocketException((int)ex.ErrorCode);
 93             }
 94         }
 95 
 96        private void socketEventArg_Completed(object sender, SocketAsyncEventArgs e)
 97         {
 98            //检查是否发送出错
 99             if (e.SocketError != SocketError.Success)
100             {
101                 if (e.SocketError == SocketError.ConnectionAborted)
102                 {
103                     Dispatcher.BeginInvoke(() => MessageBox.Show("连接超时....请重试!"));
104                 }
105                 else if (e.SocketError == SocketError.ConnectionRefused)
106                 {
107                     Dispatcher.BeginInvoke(() => MessageBox.Show("无法连接到服务器端:"+e.SocketError));
108                 }else
109                 {
110                     Dispatcher.BeginInvoke(() => MessageBox.Show("Socket连接已断开!"));
111                 }
112                 return;
113             }
114            //如果连接上,则发送数据
115             if (e.LastOperation == SocketAsyncOperation.Connect)
116             {
117                     byte[] userbytes = (byte[])e.UserToken;
118                     e.SetBuffer(userbytes, 0, userbytes.Length);
119                     socket.SendAsync(e);
120                     
121             }//如果已发送数据,则开始接收服务器回复的消息
122             else if (e.LastOperation == SocketAsyncOperation.Send)
123             {
124                 Dispatcher.BeginInvoke(() =>
125                 {
126                     listBox1.Items.Add("客户端在" + DateTime.Now.ToShortTimeString() + ",发送消息:" + MessageTextBox.Text);
127                 });
128                 byte[] userbytes = new byte[1024];
129                 e.SetBuffer(userbytes, 0, userbytes.Length);
130                 socket.ReceiveAsync(e);
131             }//接收服务器数据
132             else if (e.LastOperation == SocketAsyncOperation.Receive)
133             {
134                 string RecevieStr = Encoding.UTF8.GetString(e.Buffer, 0, e.Buffer.Length).Replace("\0", "");
135                 Dispatcher.BeginInvoke(() =>
136                 {
137                     listBox1.Items.Add("服务器在" + DateTime.Now.ToShortTimeString() + ",回复消息:" + RecevieStr);
138                 });
139                 if (RecevieStr.Contains("|"))
140                 {
141                     string[] coor = RecevieStr.Split('|');
142                     MapPoint mp1 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
143                     x = coor[0];
144                     y = coor[1];
145                     MapPoint mp2 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
146                     Dispatcher.BeginInvoke(() => { CreatPoint(mp2); });
147                     Dispatcher.BeginInvoke(() => { CreatLine(mp1, mp2);});
148                 }
149                 socket.ReceiveAsync(e); 
150             }
151         }
152 
153        private void CreatPoint(double x,double y)
154        {
155            MapPoint mp = new MapPoint(x, y);
156            Graphic g = new Graphic()
157            {
158                Symbol = new SimpleMarkerSymbol()
159                {
160                    Size = 18,
161                    Color = new SolidColorBrush(Colors.Blue),
162                    Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
163                },
164                Geometry = mp
165            };
166            graphiclayer.Graphics.Clear();
167            graphiclayer.Graphics.Add(g);
168        }
169 
170        private void CreatPoint(MapPoint mp)
171        {
172            Graphic g = new Graphic()
173            {
174                Symbol = new SimpleMarkerSymbol()
175                {
176                    Size = 18,
177                    Color = new SolidColorBrush(Colors.Blue),
178                    Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
179                },
180                Geometry = mp
181            };
182            graphiclayer.Graphics.Clear();
183            graphiclayer.Graphics.Add(g);
184        }
185 
186        private void CreatLine(MapPoint mp1,MapPoint mp2)
187        {
188            ESRI.ArcGIS.Client.Geometry.Polyline pl = new ESRI.ArcGIS.Client.Geometry.Polyline();
189            ESRI.ArcGIS.Client.Geometry.PointCollection pc = new ESRI.ArcGIS.Client.Geometry.PointCollection();
190            pc.Add(mp1);
191            pc.Add(mp2);
192            pl.Paths.Add(pc);
193            Graphic g = new Graphic()
194            {
195                Symbol=LayoutRoot.Resources["LineSymbol"] as SimpleLineSymbol,
196                Geometry = pl
197            };
198            routeLayer.Graphics.Add(g);
199        }
200 
201        private void StopButton_Click_1(object sender, RoutedEventArgs e)
202        {
203            if (socket != null)
204                socket.Shutdown(SocketShutdown.Both);
205            socket.Close();
206        }
207     }
208 }

MainPage.xaml

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:esri="http://schemas.esri.com/arcgis/client/2009" x:Class="SilverlightSocket.MainPage"
    mc:Ignorable="d">

    <Grid x:Name="LayoutRoot" Background="White" Width="900">
        <Grid.Resources>
            <esri:SimpleLineSymbol x:Key="LineSymbol" Color="Red" Style="Solid" Width="3"/>
        </Grid.Resources>
            
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.868*"/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <esri:Map x:Name="MyMap" Background="White" WrapAround="True" Grid.ColumnSpan="2">
            <esri:ArcGISTiledMapServiceLayer Url="http://www.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineStreetColor/MapServer"/>
            <esri:GraphicsLayer ID="routeLayer"/>
            <esri:GraphicsLayer ID="GraphicLayer"/>
        </esri:Map>
        <StackPanel Grid.Column="1" Background="#7F094870">
            <StackPanel.Effect>
                <DropShadowEffect/>
            </StackPanel.Effect>
            <TextBlock x:Name="textBlock1" Text="主机IP" Grid.Column="1" Margin="5,5,0,0" Foreground="#FFE7D4E3" FontWeight="Bold" />
            <TextBox x:Name="IPTextBox" Text="169.254.57.67" Grid.Column="1" d:LayoutOverrides="Width" Margin="5,5,0,0" HorizontalAlignment="Left"/>
            <TextBlock x:Name="textBlock2" Text="端口号" Grid.Column="1" Margin="5,5,0,0" Foreground="#FFE7D4E3" FontWeight="Bold" />
            <TextBox x:Name="PortTextBox" Width="51" Text="4530" Grid.Column="1" Margin="5,5,0,0" HorizontalAlignment="Left"/>
            <TextBlock  x:Name="textBlock4" Text="消息记录:" Height="23" Grid.Column="1" Margin="5,5,0,0" Foreground="#FFE7D4E3" FontWeight="Bold" />
            <ListBox  x:Name="listBox1" Grid.Column="1" Margin="5,5,0,0" Height="200" />
            <TextBlock x:Name="textBlock3" Text="发送信息内容" Height="16" Grid.Column="1" d:LayoutOverrides="Width" Margin="5,5,0,0" Foreground="#FFE7D4E3" FontWeight="Bold" VerticalAlignment="Bottom" />
            <TextBox x:Name="MessageTextBox" Grid.Column="1" Height="50" Margin="5,5,0,0" VerticalAlignment="Bottom" />
            <Button Content="发送" Height="23" x:Name="SendButton" Grid.Column="1" Margin="5,5,0,0" VerticalAlignment="Bottom" />
            <Button Content="清空" Height="23" x:Name="ClearButton" Grid.Column="1" Margin="5,5,0,0" VerticalAlignment="Bottom" />
            <Button Content="停止" Height="23" x:Name="StopButton" Grid.Column="1" Margin="5,5,0,0" VerticalAlignment="Bottom" Click="StopButton_Click_1" />
        </StackPanel>
        <esri:ScaleLine HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="30,0,0,20" Map="{Binding ElementName=MyMap}"/>
    </Grid>
</UserControl>

最后的效果:

服务器端:

客户端:

由于是图片,所以无法预览动态绘制的效果,只能看图片了。

 

(版权所有,转载请标明出处)

 
目录
相关文章
|
3月前
|
Python
python socket 简单通信
python socket 简单通信
42 1
|
3月前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
209 0
|
22天前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
92 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
22天前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
92 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
17天前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
3月前
|
网络协议 数据格式 Python
python Socket无限发送接收数据方式
Socket是指套接字,是对网络中不同主机上的应用进程之间进行双向通信的端点的一种抽象。 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。
|
3月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
101 0
|
3月前
|
网络协议
socket编程(2) -- TCP通信
socket编程(2) -- TCP通信
38 0
|
4月前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
78 0