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

原文:使用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

  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

  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数据,地图实时位置),布布扣,bubuko.com

时间: 2024-12-26 05:17:15

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

Socket 通信原理(Android客户端和服务器以TCP&amp;&amp;UDP方式互通)

ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当,还望指教. 一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是s

JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七层:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层 TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. 网络分层除了OSI模型分层,还有TCP/IP模型分层,将网络划分为四层,应用层.传输层.网际层

c++ 网络编程(二)TCP/IP linux 下多进程socket通信 多个客户端与单个服务端交互代码实现回声服务器

原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9612820.html LINUX下: 一.服务端代码 下面用了多个close来关闭文件描述符,可能有的小伙伴会有疑惑....我就说一句,创建进程的时候会把父进程的资源都复制 一份,而你这个子进程只需要保留自己需要处理的资源,其他的自然要关闭掉, 不然父亲一个儿子一个 待会打起来怎么办  嘿嘿 注意了:就像进程间的通信需要属于操作系统的资源管道来进行,套接字也属于操作系统,所以创建新进程也还是

用angular实时获取本地localStorage数据,实现一个模拟后台数据登入的效果

研究了一上午,终于做出了,实时获取本地localStorage来模拟注册登入~~~ <!DOCTYPE html><html><head lang="en"><meta charset="UTF-8"><title>我们虽然很穷,但是我们有梦想</title><script src="angular.js"></script></head>

Android登录客户端,验证码的获取,网页数据抓取与解析,HttpWatch基本使用

大家好,我是M1ko.在互联网时代的今天,如果一个App不接入互联网,那么这个App一定不会有长时间的生命周期,因此Android网络编程是每一个Android开发者必备的技能,博主是在校大学生,自学Android一年半多,正好通过一个模拟登录校园网软件,来给大家演示如何在网页上抓取我们想要的数据,以及将数据Post给服务器.如果有什么错误或改进欢迎大家指正=-= ,如果想交流博主qq 136057505 好的废话不多说看一下我们的重点 Httpwatch等软件抓取Post请求 如何获取验证码

AngularJs $http.post 数据后台获取不到数据问题 的解决过程

第一次使用 AngularJs 的 $http 模块的时候,遇到过后台获取不到前台提交数据的问题,检查代码没有发现问题,先上代码. js 代码 angular.module("newsApp", []) .constant("newsInfoUrl", "/WebPage/Page/NewsInfo/") .factory("newsService", function($http) { return { getNewsLis

.net平台下C#socket通信(上)

在开始介绍socket前先补充补充基础知识,在此基础上理解网络通信才会顺理成章,当然有基础的可以跳过去了.都是废话,进入正题. TCP/IP:Transmission Control Protocol/Internet Protocol,传输控制协议/因特网互联协议,又名网络通讯协议.简单来说:TCP控制传输数据,负责发现传输的问题,一旦有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地,而IP是负责给因特网中的每一台电脑定义一个地址,以便传输.从协议分层模型方面来讲:TCP/I

Flash Socket通信的安全策略问题 843端口

1.问题描述       将flash发布为html格式后,加载页面后,swf无法与服务器进行socket通信.Flash端显示的错误为:securityErrorHandler信息: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"] 在服务器端显示的信息是由客户端尝试进行连接,但是无法接受数据.接受的数据显

基于ArcGIS 的GPS数据地图匹配

GPS数据由于信号不良.通信异常.定位误差等原因,不能很好地落在道路上,所以需要对GPS数据进行地图匹配,与道路进行关联.而空间数据由于其特殊的数据格式,最佳的处理途径仍旧是ArcGIS Desktop系列软件. 一.路网数据检查 根据实验的需要提取出路网数据,对路网进行拓扑检查,包括不能有重叠.不能有悬挂点等,对拓扑错误进行修改:同时,需要进行"在折点处打断"操作,形成正确可用的路网数据. 二.GPS数据检查 GPS数据预处理是GPS数据使用的第一步,详见博客. 三.地图匹配 1.G