使用Socket通信實現(xiàn)Silverlight客戶端實時數(shù)據(jù)的獲取(模擬GPS數(shù)據(jù),地圖實時位置)
在上一篇中說到了Silverlight下的Socket通信,在最后的時候說到本篇將會結(jié)合地圖。下面就來看看本文實現(xiàn)的功能:
Silverlight 與服務(wù)器利用Socket通訊,實時從服務(wù)器獲取數(shù)據(jù)(本文中的數(shù)據(jù)是地理坐標),由于沒有GPS,所以本文在服務(wù)器寫了一個構(gòu)造新坐標的函數(shù)(本文是一個三角函數(shù)),然后利用Timer組件,實時調(diào)用,得到新的坐標,并將新的坐標發(fā)送給客戶端,客戶端接收到發(fā)回的新的坐標,并在地圖相應(yīng)的位置進行標識。最后在地圖上我們就會看到一個自動繪制的三角函數(shù)曲線。
關(guān)于本文的一點說明:
1.由于時間和篇幅的關(guān)系,也由于本人能力有限,所以程序還存在很多bug,不夠完善,也許你運行的時候還會拋異常,本文關(guān)注的是關(guān)鍵功能的實現(xiàn),所以希望高手勿噴,如果您有更好的方法和建議歡迎留言分享。
2.作者沒有GPS設(shè)置,相信大多數(shù)也是一樣,所以無法實際的模擬從GPS獲取數(shù)據(jù),在地圖上展示,因此本文模擬在服務(wù)器動態(tài)實時的生成坐標數(shù)據(jù),并實時發(fā)送給客戶端。不過如果您有GPS設(shè)備,實際上實現(xiàn)的過程是一樣。
3.本文的坐標數(shù)據(jù)是自己寫的一個三角函數(shù),所以最后在地圖上實時繪制的運動軌跡也是一個三角函數(shù),當然也可以換成其他任意的軌跡,只要可以寫出其坐標生成函數(shù)即可。
4.本文的具體過程是客戶端向服務(wù)器發(fā)送一個起始的坐標,當然也可以是其他的信息,只不過便于繪制和理解,所以用了一個坐標,服務(wù)器接收該坐標,并基于該坐標生成新的坐標數(shù)據(jù)。不過在實際的GPS中,只需要客戶端發(fā)送位置請求,服務(wù)器將真實的GPS坐標數(shù)據(jù)發(fā)送給客戶端即可。
5.本文的服務(wù)器端部分代碼來自于該博主的博文:
http://www.cnblogs.com/webabcd/archive/2008/12/22/1359551.html
在此感謝webabcd(王磊 MVP)的分享。
下面就來看看具體實現(xiàn)的過程。
一.服務(wù)器端
在上一篇中說到了與服務(wù)器通信,大致上的過程是客戶端發(fā)送一個信息,服務(wù)器接收客戶端信息,服務(wù)器回復(fù)一條信息,客戶端接收服務(wù)器信息。但在本文中,稍微有些不一樣。
在本文中,客戶端發(fā)送位置請求(本文客戶端發(fā)送一個用于構(gòu)造新坐標的起始坐標點),然后服務(wù)器基于接收的起始坐標,實時的生成新的坐標數(shù)據(jù),并不斷的往客戶端發(fā)送,客戶端不斷接受服務(wù)器發(fā)送來的新數(shù)據(jù),并在地圖上標示。所以這里不像之前客戶端請求一次,服務(wù)器則回復(fù)一條信息。
下面給出具體的代碼I(可以參看上面給出鏈接的博文):
服務(wù)器端界面如下:
具體過程:
1.1 啟動策略文件服務(wù)
#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 啟動服務(wù)器端Socket服務(wù),監(jiān)聽端口,連接Socket。
1.2.1 聲明類級別的變量
//客戶端傳入的起始坐標 private double startx = 0; private double starty = 0; //服務(wù)器端生成的新坐標 private double X; private double Y; //判斷是否成功接收服務(wù)器發(fā)來的新的坐標 bool receivedCoor = false; //夠找新坐標時的步長 private double step = 0;
1.2.2啟動Socket服務(wù),開始連接
private void StartupSocketServer() { //定時器,每0.3秒運行一次指定的方法 //這里可自己手動修改刷新數(shù)據(jù)的時間 _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); //創(chuàng)建終結(jié)點,獲取當前主機IP IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName()); IPEndPoint localEndPoint = new IPEndPoint(ipHost.AddressList[3], 4530); //Win7 啟動了IPV6地址,所以是3,如果為XP系統(tǒng)可換成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, "客戶端已經(jīng)連接"); try { client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client); } catch (SocketException ex) { HandleException(client, ex); } }
1.3 接收數(shù)據(jù)
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("服務(wù)器端已經(jīng)成功接收數(shù)據(jù)!"); _syncContext.Post(ResultCallback, "服務(wù)器在" + DateTime.Now.ToShortTimeString() + "接收數(shù)據(jù):" + content); } //對接受的數(shù)據(jù)進行分析 //便于簡單,客戶端發(fā)送的坐標字符串格式是"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 { // 繼續(xù)開始接收客戶端傳入的數(shù)據(jù) 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 發(fā)送數(shù)據(jù)等
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, "服務(wù)器在" + DateTime.Now.ToShortTimeString() + "發(fā)送數(shù)據(jù):" + data); } else { _clientList[i].Socket.Close(); _clientList.Remove(_clientList[i]); } } }
1.6 生成新坐標的方法,本文利用的只是一個簡單的Sin三角函數(shù),讀者可構(gòu)造自己的函數(shù)。
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定時器的觸發(fā)函數(shù),定時向調(diào)用構(gòu)造新坐標的方法,構(gòu)造新的坐標,并發(fā)送數(shù)據(jù)的到客戶端
private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { //如果服務(wù)器成功接收客戶端傳入的坐標,則向服務(wù)器發(fā)送數(shù)據(jù) if (receivedCoor == true) { newCoordinate(out X, out Y, ref step); string lat = startx.ToString("#0.00"); string lon = starty.ToString("#0.00"); //將新的坐標發(fā)送給客戶端 SendData(string.Format("{0}|{1}", X, Y)); } }
1.8 其他相關(guān)函數(shù),用于更改UI
private void ResultCallback(object result) { // 輸出相關(guān)信息 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服務(wù)Button事件,及清除消息列表
private void StartButton_Click(object sender, EventArgs e) { // 啟動后臺線程去運行 Socket 服務(wù) 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

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 //服務(wù)器端生成的新坐標 31 private double X; 32 private double Y; 33 //判斷是否成功接收服務(wù)器發(fā)來的新的坐標 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服務(wù) 51 52 } 53 54 private void StartupSocketServer() 55 { 56 //定時器,每0.3秒運行一次指定的方法 57 //這里可自己手動修改刷新數(shù)據(jù)的時間 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 //創(chuàng)建終結(jié)點,獲取當前主機IP 66 IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName()); 67 IPEndPoint localEndPoint = new IPEndPoint(ipHost.AddressList[3], 4530); 68 //Win7 啟動了IPV6地址,所以是3,如果為XP系統(tǒng)可換成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, "客戶端已經(jīng)連接"); 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("服務(wù)器端已經(jīng)成功接收數(shù)據(jù)!"); 131 _syncContext.Post(ResultCallback, "服務(wù)器在" + DateTime.Now.ToShortTimeString() + "接收數(shù)據(jù):" + content); 132 } 133 //對接受的數(shù)據(jù)進行分析 134 //便于簡單,客戶端發(fā)送的坐標字符串格式是"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 // 繼續(xù)開始接收客戶端傳入的數(shù)據(jù) 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, "服務(wù)器在" + DateTime.Now.ToShortTimeString() + "發(fā)送數(shù)據(jù):" + 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 //如果服務(wù)器成功接收客戶端傳入的坐標 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 //將新的坐標發(fā)送給客戶端 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 // 在服務(wù)端記錄異常信息,關(guān)閉導(dǎo)致異常的 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 // 輸出相關(guān)信息 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 服務(wù) 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界面如下:

客戶端實現(xiàn)的過程和上一篇文章差不多,代碼幾乎沒有變化,只不過是連續(xù)的想服務(wù)器獲取數(shù)據(jù),代碼如下:
private void socketEventArg_Completed(object sender, SocketAsyncEventArgs e) { //檢查是否發(fā)送出錯 if (e.SocketError != SocketError.Success) { if (e.SocketError == SocketError.ConnectionAborted) { Dispatcher.BeginInvoke(() => MessageBox.Show("連接超時....請重試!")); } else if (e.SocketError == SocketError.ConnectionRefused) { Dispatcher.BeginInvoke(() => MessageBox.Show("無法連接到服務(wù)器端:"+e.SocketError)); }else { Dispatcher.BeginInvoke(() => MessageBox.Show("Socket連接已斷開!")); } return; } //如果連接上,則發(fā)送數(shù)據(jù) if (e.LastOperation == SocketAsyncOperation.Connect) { byte[] userbytes = (byte[])e.UserToken; e.SetBuffer(userbytes, 0, userbytes.Length); socket.SendAsync(e); }//如果已發(fā)送數(shù)據(jù),則開始接收服務(wù)器回復(fù)的消息 else if (e.LastOperation == SocketAsyncOperation.Send) { Dispatcher.BeginInvoke(() => { listBox1.Items.Add("客戶端在" + DateTime.Now.ToShortTimeString() + ",發(fā)送消息:" + MessageTextBox.Text); }); byte[] userbytes = new byte[1024]; e.SetBuffer(userbytes, 0, userbytes.Length); socket.ReceiveAsync(e); }//接收服務(wù)器數(shù)據(jù) else if (e.LastOperation == SocketAsyncOperation.Receive) { string RecevieStr = Encoding.UTF8.GetString(e.Buffer, 0, e.Buffer.Length).Replace("\0", ""); Dispatcher.BeginInvoke(() => { listBox1.Items.Add("服務(wù)器在" + DateTime.Now.ToShortTimeString() + ",回復(fù)消息:" + RecevieStr); }); //分析服務(wù)器發(fā)送回來的坐標數(shù)據(jù),數(shù)據(jù)格式“x|y” if (RecevieStr.Contains("|")) { string[] coor = RecevieStr.Split('|'); //構(gòu)造新的坐標點 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);}); } //繼續(xù)向服務(wù)器接收數(shù)據(jù),注意不要關(guān)閉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); }
本文通過雙擊地圖獲得一個起始點坐標,并將該坐標發(fā)送給服務(wù)器,示例代碼:
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; }
關(guān)于其他部分的代碼,例如聲明圖層,情況列表再次不再強調(diào),具體請看下面代碼:
MainPage.cs


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 //建立終結(jié)點對象 72 DnsEndPoint hostEntry=new DnsEndPoint(host,port); 73 //創(chuàng)建一個Socket對象 74 socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); 75 //創(chuàng)建Socket異步事件參數(shù) 76 SocketAsyncEventArgs socketEventArg=new SocketAsyncEventArgs (); 77 //將消息轉(zhuǎn)化為發(fā)送的byte[]格式 78 byte[]buffer=Encoding.UTF8.GetBytes(MessageTextBox.Text); 79 //注冊Socket完成事件 80 socketEventArg.Completed+=new EventHandler<SocketAsyncEventArgs>(socketEventArg_Completed); 81 //設(shè)置Socket異步事件遠程終結(jié)點 82 socketEventArg.RemoteEndPoint=hostEntry; 83 //將定義好的Socket對象賦值給Socket異步事件參數(shù)的運行實例屬性 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 //檢查是否發(fā)送出錯 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("無法連接到服務(wù)器端:"+e.SocketError)); 108 }else 109 { 110 Dispatcher.BeginInvoke(() => MessageBox.Show("Socket連接已斷開!")); 111 } 112 return; 113 } 114 //如果連接上,則發(fā)送數(shù)據(jù) 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 }//如果已發(fā)送數(shù)據(jù),則開始接收服務(wù)器回復(fù)的消息 122 else if (e.LastOperation == SocketAsyncOperation.Send) 123 { 124 Dispatcher.BeginInvoke(() => 125 { 126 listBox1.Items.Add("客戶端在" + DateTime.Now.ToShortTimeString() + ",發(fā)送消息:" + MessageTextBox.Text); 127 }); 128 byte[] userbytes = new byte[1024]; 129 e.SetBuffer(userbytes, 0, userbytes.Length); 130 socket.ReceiveAsync(e); 131 }//接收服務(wù)器數(shù)據(jù) 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("服務(wù)器在" + DateTime.Now.ToShortTimeString() + ",回復(fù)消息:" + 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./markup-compatibility/2006" xmlns:esri="http://schemas./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./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="發(fā)送信息內(nèi)容" 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="發(fā)送" 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>
最后的效果:
服務(wù)器端:
客戶端:
由于是圖片,所以無法預(yù)覽動態(tài)繪制的效果,只能看圖片了。
(版權(quán)所有,轉(zhuǎn)載請標明出處)