原文:使用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 = ;
private double starty = ;
//服务器端生成的新坐标
private double X;
private double Y;
//判断是否成功接收服务器发来的新的坐标
bool receivedCoor = false;
//够找新坐标时的步长
private double step = ;
1.2.2启动Socket服务,开始连接
    private void StartupSocketServer()
{
//定时器,每0.3秒运行一次指定的方法
//这里可自己手动修改刷新数据的时间
_timer = new System.Timers.Timer();
_timer.Interval = ;
_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[], );
//Win7 启动了IPV6地址,所以是3,如果为XP系统可换成0,1再试试
_syncContext.Post(ChangeIPText, ipHost.AddressList[].ToString());
//绑定端口
_listener.Bind(localEndPoint);
_listener.Listen(); 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, , 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 = ;
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 == )
continue;
client.RececivedByte.Add(b);
} string receivedString = UTF8Encoding.UTF8.GetString(client.Buffer, , count);
if (client.Socket.Connected && client.Socket.Available == && 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[]);
starty = Convert.ToDouble(coordinates[]);
_syncContext.Post(ChangeReceivedText, receivedString);
step = ;
receivedCoor = true;
} try
{
// 继续开始接收客户端传入的数据
if (client.Socket.Connected)
client.Socket.BeginReceive(client.Buffer, , client.Buffer.Length, , 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 = ; i < _clientList.Count;i++ )
{ if (_clientList[i].Socket.Connected)
{
_clientList[i].Socket.BeginSend(byteData, , 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 + * step; longitude = starty + * 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

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO; namespace WindowsServer
{
public partial class Form1 : Form
{
SynchronizationContext _syncContext;
System.Timers.Timer _timer;
private string _endMarker = "^"; private Socket _listener; private ManualResetEvent _connectDone = new ManualResetEvent(false);
private List<ClientSocketPacket> _clientList = new List<ClientSocketPacket>(); //客户端传入的起始坐标
private double startx = ;
private double starty = ;
//服务器端生成的新坐标
private double X;
private double Y;
//判断是否成功接收服务器发来的新的坐标
bool receivedCoor = false;
//够找新坐标时的步长
private double step = ; public Form1()
{
InitializeComponent();
#region Start The Policy Server 验证策略文件
PolicySocketServer StartPolicyServer = new PolicySocketServer();
Thread th = new Thread(new ThreadStart(StartPolicyServer.StartSocketServer));
th.IsBackground = true;
th.Start();
#endregion //UI线程
_syncContext = SynchronizationContext.Current;
//启动线程运行Socket服务 } private void StartupSocketServer()
{
//定时器,每0.3秒运行一次指定的方法
//这里可自己手动修改刷新数据的时间
_timer = new System.Timers.Timer();
_timer.Interval = ;
_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[], );
//Win7 启动了IPV6地址,所以是3,如果为XP系统可换成0,1再试试
_syncContext.Post(ChangeIPText, ipHost.AddressList[].ToString());
//绑定端口
_listener.Bind(localEndPoint);
_listener.Listen(); 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, , client.Buffer.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);
}
catch (SocketException ex)
{
HandleException(client, ex);
}
} private void OnDataReceived(IAsyncResult result)
{
ClientSocketPacket client = result.AsyncState as ClientSocketPacket;
int count = ;
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 == )
continue;
client.RececivedByte.Add(b);
} string receivedString = UTF8Encoding.UTF8.GetString(client.Buffer, , count);
if (client.Socket.Connected && client.Socket.Available == && 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[]);
starty = Convert.ToDouble(coordinates[]);
_syncContext.Post(ChangeReceivedText, receivedString);
step = ;
receivedCoor = true;
} try
{
// 继续开始接收客户端传入的数据
if (client.Socket.Connected)
client.Socket.BeginReceive(client.Buffer, , client.Buffer.Length, , new AsyncCallback(OnDataReceived), client);
}
catch (SocketException ex)
{
HandleException(client, ex);
}
} private void SendData(string data)
{
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
for (int i = ; i < _clientList.Count;i++ )
{ if (_clientList[i].Socket.Connected)
{
_clientList[i].Socket.BeginSend(byteData, , 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]);
}
}
} private void OnDataSend(IAsyncResult result)
{
ClientSocketPacket client = result.AsyncState as ClientSocketPacket;
try
{
if (client.Socket.Connected)
client.Socket.EndSend(result);
}
catch (SocketException ex)
{
HandleException(client, ex);
}
} 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));
}
} private void newCoordinate(out double latitude, out double longitude, ref double step)
{
latitude = startx + * step; longitude = starty + * Math.Sin(step); step = step + 0.1;
} private void HandleException(ClientSocketPacket client, SocketException ex)
{
if (client.Socket == null)
return;
// 在服务端记录异常信息,关闭导致异常的 Socket,并将其清除出客户端 Socket 列表
_syncContext.Post(ResultCallback, client.Socket.RemoteEndPoint.ToString() + " - " + ex.Message);
client.Socket.Close();
_clientList.Remove(client);
} 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();
}
private void StartButton_Click(object sender, EventArgs e)
{
// 启动后台线程去运行 Socket 服务
Thread thread = new Thread(new ThreadStart(StartupSocketServer));
thread.IsBackground = true;
thread.Start();
} private void StopButton_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
}
}

二、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, , 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[];
e.SetBuffer(userbytes, , userbytes.Length);
socket.ReceiveAsync(e);
}//接收服务器数据
else if (e.LastOperation == SocketAsyncOperation.Receive)
{
string RecevieStr = Encoding.UTF8.GetString(e.Buffer, , 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[];
y = coor[];
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 = ,
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=,
Color=new SolidColorBrush(Colors.Blue),
Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
},
Geometry=mp
};
graphiclayer.Graphics.Add(g);
MessageTextBox.Text = x + "|" + y;
}

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

MainPage.cs

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Net.Sockets;
using System.Text;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Symbols;
using ESRI.ArcGIS.Client.Tasks;
namespace SilverlightSocket
{
public partial class MainPage : UserControl
{
private Socket socket;
private string x, y;
GraphicsLayer graphiclayer;
GraphicsLayer routeLayer;
public MainPage()
{
InitializeComponent();
SendButton.Click += new RoutedEventHandler(SendButton_Click);
ClearButton.Click += ClearButton_Click;
MyMap.MouseClick+=MyMap_MouseClick;
graphiclayer = MyMap.Layers["GraphicLayer"] as GraphicsLayer;
routeLayer = MyMap.Layers["routeLayer"] as GraphicsLayer;
} 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=,
Color=new SolidColorBrush(Colors.Blue),
Style=SimpleMarkerSymbol.SimpleMarkerStyle.Circle
},
Geometry=mp
};
graphiclayer.Graphics.Add(g);
MessageTextBox.Text = x + "|" + y;
} void ClearButton_Click(object sender, RoutedEventArgs e)
{
listBox1.Items.Clear();
} private void SendButton_Click(object sender, RoutedEventArgs e)
{
if(string.IsNullOrEmpty(IPTextBox.Text)||string.IsNullOrEmpty(PortTextBox.Text))
{
MessageBox.Show ("请输入主机IP地址和端口号!");
return;
}
//ip地址
string host=IPTextBox.Text.Trim();
//端口号
int port=Convert.ToInt32(PortTextBox.Text.Trim());
//建立终结点对象
DnsEndPoint hostEntry=new DnsEndPoint(host,port);
//创建一个Socket对象
socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//创建Socket异步事件参数
SocketAsyncEventArgs socketEventArg=new SocketAsyncEventArgs ();
//将消息转化为发送的byte[]格式
byte[]buffer=Encoding.UTF8.GetBytes(MessageTextBox.Text);
//注册Socket完成事件
socketEventArg.Completed+=new EventHandler<SocketAsyncEventArgs>(socketEventArg_Completed);
//设置Socket异步事件远程终结点
socketEventArg.RemoteEndPoint=hostEntry;
//将定义好的Socket对象赋值给Socket异步事件参数的运行实例属性
socketEventArg.UserToken = buffer;
//socketEventArg.UserToken = socket;
try
{
socket.ConnectAsync(socketEventArg);
}
catch(SocketException ex)
{
throw new SocketException((int)ex.ErrorCode);
}
} 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, , 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[];
e.SetBuffer(userbytes, , userbytes.Length);
socket.ReceiveAsync(e);
}//接收服务器数据
else if (e.LastOperation == SocketAsyncOperation.Receive)
{
string RecevieStr = Encoding.UTF8.GetString(e.Buffer, , e.Buffer.Length).Replace("\0", "");
Dispatcher.BeginInvoke(() =>
{
listBox1.Items.Add("服务器在" + DateTime.Now.ToShortTimeString() + ",回复消息:" + RecevieStr);
});
if (RecevieStr.Contains("|"))
{
string[] coor = RecevieStr.Split('|');
MapPoint mp1 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
x = coor[];
y = coor[];
MapPoint mp2 = new MapPoint(Convert.ToDouble(x), Convert.ToDouble(y));
Dispatcher.BeginInvoke(() => { CreatPoint(mp2); });
Dispatcher.BeginInvoke(() => { CreatLine(mp1, mp2);});
}
socket.ReceiveAsync(e);
}
} private void CreatPoint(double x,double y)
{
MapPoint mp = new MapPoint(x, y);
Graphic g = new Graphic()
{
Symbol = new SimpleMarkerSymbol()
{
Size = ,
Color = new SolidColorBrush(Colors.Blue),
Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
},
Geometry = mp
};
graphiclayer.Graphics.Clear();
graphiclayer.Graphics.Add(g);
} private void CreatPoint(MapPoint mp)
{
Graphic g = new Graphic()
{
Symbol = new SimpleMarkerSymbol()
{
Size = ,
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 StopButton_Click_1(object sender, RoutedEventArgs e)
{
if (socket != null)
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
}

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数据,地图实时位置)的更多相关文章

  1. DataTable相关操作,筛选,取前N条数据,获取指定列数据

    DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ...

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

    转载地址:http://blog.csdn.net/mad1989/article/details/9147661 ZERO.前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当 ...

  3. Socket通信——服务器和客户端相互通信

    所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.  Socket和S ...

  4. 使用 Socket 通信实现 FTP 客户端程序(来自IBM)

    FTP 客户端如 FlashFXP,File Zilla 被广泛应用,原理上都是用底层的 Socket 来实现.FTP 客户端与服务器端进行数据交换必须建立两个套接字,一个作为命令通道,一个作为数据通 ...

  5. 使用Socket通信实现FTP客户端程序

    FTP 客户端如 FlashFXP,File Zilla 被广泛应用,原理上都是用底层的 Socket 来实现.FTP 客户端与服务器端进行数据交换必须建立两个套接字,一个作为命令通道,一个作为数据通 ...

  6. socket通信——通过Udp传输方式,将一段文字数据发送出去

    需求:通过Udp传输方式,将一段文字数据发送出去 定义一个Udp发送端 思路: 1.建立updsocket服务 2.提供数据,并将数据封装到数据包中. 3.通过socket服务的发送功能,将数据包发出 ...

  7. 利用大数据技术处理海量GPS数据

    我秀中国物联网地图服务平台目前接入的监控车辆近百万辆,每天采集GPS数据7亿多条,产生日志文件70GB,使用传统的数据处理方式非常耗时. 比如,仅仅对GPS做一些简单的统计分析,程序就需要几个小时才能 ...

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

    OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七 ...

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

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9612820.html 锲子-- 预备知识优雅的关闭套接字连接: 基于TCP的半关闭 TCP中的 ...

随机推荐

  1. T-Sql(一)简单语法

    原文:T-Sql(一)简单语法 Sql Server是鄙人学习的第一种数据库,对Sql Server有一种特别的情感,下面就说一下Sql Server的简单语法,适用初学者. 1,创建数据库creat ...

  2. OC动态创建的问题变量数组.有数组,在阵列13要素,第一个数据包阵列,每3元素为一组,分成若干组,这些数据包的统一管理。最后,一个数组.(要动态地创建一个数组).两种方法

    <span style="font-size:24px;">//////第一种方法 //        NSMutableArray *arr = [NSMutable ...

  3. Windows Server 2008 R2 SP1 下载地址

    Windows Server 2008 R2 SP1 http://download.microsoft.com/download/0/A/F/0AFB5316-3062-494A-AB78-7FB0 ...

  4. ssh远程登录报错REMOTE HOST IDENTIFICATION HAS CHANGED!解决方式及原因

    注意,文档中的ip和指纹已经替换为了ip.ip.ip.ip 和aa:... ,以免引起不必要的误会. icode@test:~/lab/dir/sadf$ ssh remote_name@ip.ip. ...

  5. BZOJ 1901 Dynamic Rankings 树董事长

    标题效果:间隔可以改变k少 我的两个天树牌主席... 隔断Count On A Tree 之后我一直认为,随着树的主席的变化是分域林木覆盖率可持久段树. .. 事实上,我是误导... 尼可持久化线段树 ...

  6. Ext,保存输入记录,并会提示输入

    Ext的ComboBox组件使用非常多,通过配置输入框可以被允许成为一个.并可以存储输入记录,记录提示的基础,然后进行再次进入,以提高的用户体验输入操作. 代码非常easy,基本操作,如以下: // ...

  7. 设置状态栏样式Demo

    达到的效果: 色有黑色变为了白色 //设置状态条的样式 - (UIStatusBarStyle)preferredStatusBarStyle { returnUIStatusBarStyleLigh ...

  8. Android在ListView滑动数据混乱

    我相信做过Android应用程序开发或多或少都遇到了这个问题.或者是在ListView数据损坏幻灯片事件.要么GridView数据损坏幻灯片事件. 让我们来看看一个网友写的文章,个人感觉还不错的文章: ...

  9. MySql分析算法作品索引(马上,只是说说而已B-tree)

    刚开始学习的时候,百度搜索.但我发现很难理解了很多的太复杂,各种物品的整合总结(建议可能看到的文字,我不明白也没关系,再看看操作步骤图,然后结合文,所以,一切都清楚了很多) B-tree.B这是bal ...

  10. NSIS:使用FileFunc.nsh头文件判断文件版本

    原文 NSIS:使用FileFunc.nsh头文件判断文件版本 这里,轻狂拿WMP10做一个例子.关于WMP10的原始安装文件,可以下载后通过/C /T:D:\Windows Media Player ...