在上一篇中说到了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(可以参看上面给出链接的博文):

 服务器端界面如下:

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

具体过程:

  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


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

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

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


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

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

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>


最后的效果:

服务器端:

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

客户端:

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

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

 

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