[索引页]
[源码下载]
作者: webabcd
介绍
Silverlight 2.0 Socket通信。开发一个多人聊天室
服务端:实例化Socket, 绑定, 监听, 连接, 接收数据, 发送数据
客户端:实例化Socket, 指定服务端地址, 连接, 接收数据, 发送数据
在线DEMO
http://webabcd.blog.51cto.com/1787395/342779
示例
1、Policy服务(向客户端发送策略文件的服务)
clientaccesspolicy.xml
[源码下载]
稳扎稳打Silverlight(24) - 2.0通信之Socket, 开发一个多人聊天室
作者: webabcd
介绍
Silverlight 2.0 Socket通信。开发一个多人聊天室
服务端:实例化Socket, 绑定, 监听, 连接, 接收数据, 发送数据
客户端:实例化Socket, 指定服务端地址, 连接, 接收数据, 发送数据
在线DEMO
http://webabcd.blog.51cto.com/1787395/342779
示例
1、Policy服务(向客户端发送策略文件的服务)
clientaccesspolicy.xml
<?
xml
version
="1.0" encoding
="utf-8"
?>
< access-policy >
< cross-domain-access >
< policy >
< allow-from >
< domain uri ="*" />
</ allow-from >
< grant-to >
< socket-resource port ="4502-4534" protocol ="tcp" />
</ grant-to >
</ policy >
</ cross-domain-access >
</ access-policy >
< access-policy >
< cross-domain-access >
< policy >
< allow-from >
< domain uri ="*" />
</ allow-from >
< grant-to >
< socket-resource port ="4502-4534" protocol ="tcp" />
</ grant-to >
</ policy >
</ cross-domain-access >
</ access-policy >
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.Net.Sockets;
using System.IO;
using System.Net;
namespace PolicyServer
{
public partial class Main : Form
{
// 客户端 socket 发送到服务端的对策略文件的请求信息
private readonly string _policyRequestString = "<policy-file-request/>";
private Socket _listener; // 服务端监听的 socket
private byte[] _policyBuffer; // 服务端策略文件的 buffer
private byte[] _requestBuffer; // 客户端 socket 发送的请求信息的 buffer
private int _received; // 接收到的信息字节数
private bool _flag = false; // 标志位。服务端是否要处理传入的连接
System.Threading.SynchronizationContext _syncContext;
public Main()
{
InitializeComponent();
_flag = true;
lblStatus.Text = "PolicyServer状态:启动";
lblStatus.ForeColor = Color.Green;
// 启动 PolicyServer
StartupPolicyServer();
// UI 线程
_syncContext = System.Threading.SynchronizationContext.Current;
}
private void btnStartup_Click( object sender, EventArgs e)
{
_flag = true;
lblStatus.Text = "PolicyServer状态:启动";
lblStatus.ForeColor = Color.Green;
}
private void btnPause_Click( object sender, EventArgs e)
{
_flag = false;
lblStatus.Text = "PolicyServer状态:暂停";
lblStatus.ForeColor = Color.Red;
}
/// <summary>
/// 启动 PolicyServer
/// </summary>
private void StartupPolicyServer()
{
string policyFile = Path.Combine(Application.StartupPath, "clientaccesspolicy.xml");
using (FileStream fs = new FileStream(policyFile, FileMode.Open, FileAccess.Read))
{
// 将策略文件的内容写入 buffer
_policyBuffer = new byte[fs.Length];
fs.Read(_policyBuffer, 0, _policyBuffer.Length);
}
// 初始化 socket , 然后与端口绑定, 然后对端口进行监听
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind( new IPEndPoint(IPAddress.Any, 943)); // socket 请求策略文件使用 943 端口
_listener.Listen(100);
// 开始接受客户端传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
}
private void OnClientConnect(IAsyncResult result)
{
if (!_flag)
{
// PolicyServer 停用的话,则不再处理传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
return;
}
Socket client; // 客户端发过来的 socket
try
{
// 完成接受客户端传入的连接的这个异步操作,并返回客户端连入的 socket
client = _listener.EndAccept(result);
}
catch (SocketException)
{
return;
}
_requestBuffer = new byte[_policyRequestString.Length];
_received = 0;
try
{
// 开始接收客户端传入的数据
client.BeginReceive(_requestBuffer, 0, _policyRequestString.Length, SocketFlags.None, new AsyncCallback(OnReceive), client);
}
catch (SocketException)
{
// socket 出错则关闭客户端 socket
client.Close();
}
// 继续开始接受客户端传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
}
private void OnReceive(IAsyncResult result)
{
Socket client = result.AsyncState as Socket;
try
{
// 完成接收数据的这个异步操作,并计算累计接收的数据的字节数
_received += client.EndReceive(result);
if (_received < _policyRequestString.Length)
{
// 没有接收到完整的数据,则继续开始接收
client.BeginReceive(_requestBuffer, _received, _policyRequestString.Length - _received, SocketFlags.None, new AsyncCallback(OnReceive), client);
return;
}
// 把接收到的数据转换为字符串
string request = System.Text.Encoding.UTF8.GetString(_requestBuffer, 0, _received);
if (StringComparer.InvariantCultureIgnoreCase.Compare(request, _policyRequestString) != 0)
{
// 如果接收到的数据不是“<policy-file-request/>”,则关闭客户端 socket
client.Close();
return;
}
// 开始向客户端发送策略文件的内容
client.BeginSend(_policyBuffer, 0, _policyBuffer.Length, SocketFlags.None, new AsyncCallback(OnSend), client);
}
catch (SocketException)
{
// socket 出错则关闭客户端 socket
client.Close();
}
}
private void OnSend(IAsyncResult result)
{
Socket client = result.AsyncState as Socket;
try
{
// 完成将信息发送到客户端的这个异步操作
client.EndSend(result);
// 获取客户端的ip地址及端口号,并显示
_syncContext.Post(ResultCallback, client.LocalEndPoint.ToString());
}
finally
{
// 关闭客户端 socket
client.Close();
}
}
void ResultCallback( object result)
{
// 输出客户端的ip地址及端口号
txtMsg.Text += result.ToString() + "\r\n";
}
}
}
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.Net.Sockets;
using System.IO;
using System.Net;
namespace PolicyServer
{
public partial class Main : Form
{
// 客户端 socket 发送到服务端的对策略文件的请求信息
private readonly string _policyRequestString = "<policy-file-request/>";
private Socket _listener; // 服务端监听的 socket
private byte[] _policyBuffer; // 服务端策略文件的 buffer
private byte[] _requestBuffer; // 客户端 socket 发送的请求信息的 buffer
private int _received; // 接收到的信息字节数
private bool _flag = false; // 标志位。服务端是否要处理传入的连接
System.Threading.SynchronizationContext _syncContext;
public Main()
{
InitializeComponent();
_flag = true;
lblStatus.Text = "PolicyServer状态:启动";
lblStatus.ForeColor = Color.Green;
// 启动 PolicyServer
StartupPolicyServer();
// UI 线程
_syncContext = System.Threading.SynchronizationContext.Current;
}
private void btnStartup_Click( object sender, EventArgs e)
{
_flag = true;
lblStatus.Text = "PolicyServer状态:启动";
lblStatus.ForeColor = Color.Green;
}
private void btnPause_Click( object sender, EventArgs e)
{
_flag = false;
lblStatus.Text = "PolicyServer状态:暂停";
lblStatus.ForeColor = Color.Red;
}
/// <summary>
/// 启动 PolicyServer
/// </summary>
private void StartupPolicyServer()
{
string policyFile = Path.Combine(Application.StartupPath, "clientaccesspolicy.xml");
using (FileStream fs = new FileStream(policyFile, FileMode.Open, FileAccess.Read))
{
// 将策略文件的内容写入 buffer
_policyBuffer = new byte[fs.Length];
fs.Read(_policyBuffer, 0, _policyBuffer.Length);
}
// 初始化 socket , 然后与端口绑定, 然后对端口进行监听
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind( new IPEndPoint(IPAddress.Any, 943)); // socket 请求策略文件使用 943 端口
_listener.Listen(100);
// 开始接受客户端传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
}
private void OnClientConnect(IAsyncResult result)
{
if (!_flag)
{
// PolicyServer 停用的话,则不再处理传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
return;
}
Socket client; // 客户端发过来的 socket
try
{
// 完成接受客户端传入的连接的这个异步操作,并返回客户端连入的 socket
client = _listener.EndAccept(result);
}
catch (SocketException)
{
return;
}
_requestBuffer = new byte[_policyRequestString.Length];
_received = 0;
try
{
// 开始接收客户端传入的数据
client.BeginReceive(_requestBuffer, 0, _policyRequestString.Length, SocketFlags.None, new AsyncCallback(OnReceive), client);
}
catch (SocketException)
{
// socket 出错则关闭客户端 socket
client.Close();
}
// 继续开始接受客户端传入的连接
_listener.BeginAccept( new AsyncCallback(OnClientConnect), null);
}
private void OnReceive(IAsyncResult result)
{
Socket client = result.AsyncState as Socket;
try
{
// 完成接收数据的这个异步操作,并计算累计接收的数据的字节数
_received += client.EndReceive(result);
if (_received < _policyRequestString.Length)
{
// 没有接收到完整的数据,则继续开始接收
client.BeginReceive(_requestBuffer, _received, _policyRequestString.Length - _received, SocketFlags.None, new AsyncCallback(OnReceive), client);
return;
}
// 把接收到的数据转换为字符串
string request = System.Text.Encoding.UTF8.GetString(_requestBuffer, 0, _received);
if (StringComparer.InvariantCultureIgnoreCase.Compare(request, _policyRequestString) != 0)
{
// 如果接收到的数据不是“<policy-file-request/>”,则关闭客户端 socket
client.Close();
return;
}
// 开始向客户端发送策略文件的内容
client.BeginSend(_policyBuffer, 0, _policyBuffer.Length, SocketFlags.None, new AsyncCallback(OnSend), client);
}
catch (SocketException)
{
// socket 出错则关闭客户端 socket
client.Close();
}
}
private void OnSend(IAsyncResult result)
{
Socket client = result.AsyncState as Socket;
try
{
// 完成将信息发送到客户端的这个异步操作
client.EndSend(result);
// 获取客户端的ip地址及端口号,并显示
_syncContext.Post(ResultCallback, client.LocalEndPoint.ToString());
}
finally
{
// 关闭客户端 socket
client.Close();
}
}
void ResultCallback( object result)
{
// 输出客户端的ip地址及端口号
txtMsg.Text += result.ToString() + "\r\n";
}
}
}
2、Socket服务端(聊天室的服务端)
ClientSocketPacket.cs
ClientSocketPacket.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SocketServer
{
/// <summary>
/// 对客户端 Socket 及其他相关信息做一个封装
/// </summary>
public class ClientSocketPacket
{
/// <summary>
/// 客户端 Socket
/// </summary>
public System.Net.Sockets.Socket Socket { get; set; }
private byte[] _buffer;
/// <summary>
/// 为该客户端 Socket 开辟的缓冲区
/// </summary>
public byte[] Buffer
{
get
{
if (_buffer == null)
_buffer = new byte[32];
return _buffer;
}
}
private List< byte> _receivedByte;
/// <summary>
/// 客户端 Socket 发过来的信息的字节集合
/// </summary>
public List< byte> ReceivedByte
{
get
{
if (_receivedByte == null)
_receivedByte = new List< byte>();
return _receivedByte;
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SocketServer
{
/// <summary>
/// 对客户端 Socket 及其他相关信息做一个封装
/// </summary>
public class ClientSocketPacket
{
/// <summary>
/// 客户端 Socket
/// </summary>
public System.Net.Sockets.Socket Socket { get; set; }
private byte[] _buffer;
/// <summary>
/// 为该客户端 Socket 开辟的缓冲区
/// </summary>
public byte[] Buffer
{
get
{
if (_buffer == null)
_buffer = new byte[32];
return _buffer;
}
}
private List< byte> _receivedByte;
/// <summary>
/// 客户端 Socket 发过来的信息的字节集合
/// </summary>
public List< byte> ReceivedByte
{
get
{
if (_receivedByte == null)
_receivedByte = new List< byte>();
return _receivedByte;
}
}
}
}
OK
[源码下载]
[源码下载]
本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/343813
,如需转载请自行联系原作者