原文:使用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. 制作service服务,shell脚本小例子(来自网络)

    事先准备工作:源码安装apache .安装目录为/usr/local/httpd 任务需求:1.可通过 service httpd start|stop|status|restart 命令对服务进行控 ...

  2. 【C语言探索之旅】 第二部分第五课:预处理

    内容简介 1.课程大纲 2.第二部分第五课: 预处理 3.第二部分第六课预告:   创建你自己的变量类型 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语 ...

  3. c# winfrom DataGridView使行高不可改变,使列头高度不可改变,

    // 禁止用户改变DataGridView1的所有列的列宽 //DataGridView1.AllowUserToResizeColumns = false; //禁止用户改变DataGridView ...

  4. 真实故事:网站遭遇DOS攻击

     网站遭遇DOS攻击 一个.事件背景 长假对于IT人员来说是个短暂的休整时期,可IT系统却一时也不能停.越是节假日,越可能出大问题,以下要讲述的就是一起遭受DOS攻击的案例. 春节长假刚过完,小李 ...

  5. SQL Server 内存泄露(memory leak)——游标导致的内存问题

    原文:SQL Server 内存泄露(memory leak)--游标导致的内存问题 转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql ...

  6. Path和ClassPath差异

    1.Path角色 Path它用于指定Java路径的命令,当我们想编译Java当需要使用的程序javac.exe并运行.class当文件需要使用java.exe,此时Path设置的路径就发生作用了.由于 ...

  7. (spring-第14回【IoC基础篇】)国际化信息 (转)

    国际化又称为本地化. 当你把手机的language由中文切换到英文时,你的微信也相应改用英语,这就是i18n国际化.一般来说,应用软件提供一套不同语言的资源文件,放到特定目录中,应用根据不同语言的操作 ...

  8. 站长VS微商 你选择哪个?

    近期,站长圈里盛行起了一阵面膜风.我刷空间和微信朋友圈的时候,常常看到一些朋友在卖面膜,不光女童鞋在卖,男屌丝站长也在卖. 不光普通人在卖.行业圈的自媒体明星大佬也在卖. 我们暂且称卖面膜的童鞋为微商 ...

  9. ORA-12545: Connect failed because target host or object does not exist

    [oracle@ybdbtest oradata]$ sqlplus /nolog SQL*Plus: Release 9.2.0.4.0 - Production on Thu Jun 26 10: ...

  10. Android Dalvikvm 内存管理理解

    网上非常多文件介绍了 jvm 内存管理的理论,但在 Dalvikvm 中,到底是怎样实现的. 这几天猛看了 Dalvikvm 的源码,说一下我的理解: 在大层面上讲跟理论一样,jvm 把内存分成了一些 ...