Silverlight Socket通信
public delegate void ConnectEventHandler();//定义连接委托
public delegate void SendEventHandler();//定义发送委托
public delegate void PackageEventHandler();//定义收到一个完整的数据包委托
public class SocketHelper
{
private Socket socket;//定义Socket
private SocketAsyncEventArgs socketArgs;//定义Socket参数
public event ConnectEventHandler ConnectCompleted;//定义连接成功后触发的事件
public event SendEventHandler SendCompleted;//定义发送成功后触发的事件
public event PackageEventHandler PackageCompleted;//定义收到一个完整的数据包后触发的事件
private byte[] tempBuffer = new byte[1024];//临时缓冲区,只存放不完整的包
private List<byte[]> packageList = new List<byte[]>();//存放完整的包的集合
private int packLen = 0;//当前包的长度
private int packLenLeft = 0;//当前包还需要多少字节
private bool state = true;//当前是准备接收新包还是旧包,true表示接收新包。
//如果socket发送成功,则返回true
private bool isSend = true;
public bool IsSend
{
get { return isSend; }
}
/// <summary>
/// 构造函数,初始化socket,设置相关属性和参数
/// </summary>
public SocketHelper()
{
socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketArgs = new SocketAsyncEventArgs();
}
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="ipAddress">服务器IP地址</param>
/// <param name="port">端口号</param>
public void Connect(string ipAddress, int port)
{
//设置到远程终节点属性
socketArgs.RemoteEndPoint = new DnsEndPoint(ipAddress, port);
//设置好当Socket任何一个动作完成时的回调函数。
socketArgs.Completed += new EventHandler<SocketAsyncEventArgs>(socketArgs_Completed);
//执行异步连接。
socket.ConnectAsync(socketArgs);
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="content">消息内容</param>
public bool Send(string content)
{
//默认连接存在
bool isConnect = true;
if (socket != null && socket.Connected)
{
if (!string.IsNullOrEmpty(content.Trim()))
{
//将传入的字符串转换的Byte字节数组
byte[] bytes = Encoding.UTF8.GetBytes(content);
//新实例化一个Socket参数
socketArgs = new SocketAsyncEventArgs();
//设置Socket参数的缓冲区参数,将我们的字节数组设置为Socket的缓冲区。
socketArgs.SetBuffer(bytes, 0, bytes.Length);
//发送数据
try
{
socket.SendAsync(socketArgs);
}
catch
{
isSend = false;
}
finally
{
//触发客户端事件
if (SendCompleted != null)
{
SendCompleted();
}
}
}
}
else
{
isConnect = false;
}
return isConnect;
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
socket.Close();
}
/// <summary>
/// 获取单个包
/// </summary>
/// <returns>单个包或null</returns>
public byte[] GetPackage()
{
if (packageList.Count > 0)
{
byte[] SingleByte = packageList[0];
packageList.RemoveAt(0);
return SingleByte;
}
else
{
return null;
}
}
/// <summary>
/// 任何一个Socket动作完成,都回调该函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void socketArgs_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
ProcessConnect(e);
break;
//case SocketAsyncOperation.Send:
// ProcessSend(e);
// break;
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
}
}
/// <summary>
/// 连接成功后,触发的客户端事件
/// </summary>
private void ProcessConnect(SocketAsyncEventArgs e)
{
//连接成功后,就进入准备接收状态
ProcessSend(e);
//触发客户端事件
if (ConnectCompleted != null)
{
ConnectCompleted();
}
}
/// <summary>
/// 执行等待接收服务器发回的数据(不管有没有发送操作)
/// </summary>
private void ProcessSend(SocketAsyncEventArgs e)
{
//定义个空的字节数组,设置好其大小
byte[] bytes = new byte[1024];
//将前面定义字节数组设置成缓冲区
e.SetBuffer(bytes, 0, bytes.Length);
//执行异步接收
socket.ReceiveAsync(e);
}
/// <summary>
/// 接收完成后,处理数据
/// </summary>
/// <param name="e"></param>
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (socket.Connected)
{
//在执行好接收后,本地SOCKET的缓冲区就会被服务器发送的数据填充。
//将收到的零散数据放到临时缓冲区中
//创建一个新数组,存放传来的数据
byte[] realByte = new byte[e.BytesTransferred];
//去buffer中前N位有效数据
Array.Copy(e.Buffer, 0, realByte, 0, e.BytesTransferred);
//处理数据
DisposeByte(realByte);
//将socket一直处于接收状态
socket.ReceiveAsync(e);
}
}
/// <summary>
/// 返回实际的字节数组
/// </summary>
/// <param name="arrByte">目标数组</param>
/// <returns>实际数组</returns>
private byte[] GetRealByte(byte[] arrByte)
{
int tag = arrByte.Length;
for (int i = arrByte.Length - 1; i >= 0; i--)
{
if (arrByte[i].ToString() != "0")
{
break;
}
tag--;
}
byte[] realByte = new byte[tag];
Array.Copy(arrByte, 0, realByte, 0, tag);
return realByte;
}
/// <summary>
/// 处理从服务器端发来的数据,对包进行分析
/// </summary>
/// <param name="arrByte">服务器端发来的数据</param>
private void DisposeByte(byte[] arrByte)
{
byte[] realByte = GetRealByte(arrByte);//获得实际的字节数组
int recLen = realByte.Length;//收到的包还剩下多少
int sepIndex = -1;//分隔符所在的位置
while (recLen > 0)
{
if (state)
{
//准备接收新包
//获取第一个分隔符所在的位置
for (int i = 0; i < realByte.Length; i++)
{
if (realByte[i].ToString() == "31")
{
sepIndex = i;
break;
}
}
if (sepIndex >= 0)
{
//找到分隔符
string strLen = "";
int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置
if (buffIndex == 0)
{
for (int j = 0; j < sepIndex; j++)
{
strLen += Encoding.UTF8.GetString(realByte, j, 1);
}
packLen = Convert.ToInt32(strLen);
packLenLeft = packLen;
recLen = recLen - sepIndex - 1;
state = false;
}
else
{
for (int k = 0; k < buffIndex; k++)
{
strLen += Encoding.UTF8.GetString(tempBuffer, k, 1);
}
for (int l = 0; l < sepIndex; l++)
{
strLen += Encoding.UTF8.GetString(realByte, l, 1);
}
packLen = Convert.ToInt32(strLen);
packLenLeft = packLen;
recLen = recLen - sepIndex - 1;
state = false;
}
}
else
{
//没找到分隔符
int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置
//将剩下的包放到缓冲区中
Array.Copy(realByte, 0, tempBuffer, buffIndex, realByte.Length);
recLen = 0;
//更改状态
state = true;
}
}
else
{
//准备接收旧包
if (packLenLeft <= recLen)
{
//需要的长度小于等于字节数组剩下的长度,因此可以取得完整包
int buffIndex = GetRealByte(tempBuffer).Length;//查看缓冲区索引的位置,如果为0,则表示缓冲区为空
if (buffIndex == 0)
{
//将完整的包放到集合中
byte[] tempByte1 = new byte[packLen];
Array.Copy(realByte, sepIndex + 1, tempByte1, 0, packLen);
packageList.Add(tempByte1);
//计算收到的包还剩下多少
recLen = recLen - packLen;
//生成新的realByte
byte[] tempByte2 = new byte[recLen];
Array.Copy(realByte, sepIndex + packLen + 1, tempByte2, 0, recLen);
realByte = new byte[recLen];
Array.Copy(tempByte2, 0, realByte, 0, tempByte2.Length);
//更改状态
state = true;
}
else
{
if (sepIndex == -1)
{
Array.Copy(realByte, 0, tempBuffer, buffIndex, packLenLeft);
}
else
{
Array.Copy(realByte, 0, tempBuffer, buffIndex, packLenLeft + sepIndex + 1);
}
int index = 0;
//获取tempBuffer中第一个分隔符所在的位置
for (int i = 0; i < tempBuffer.Length; i++)
{
if (tempBuffer[i].ToString() == "31")
{
index = i;
break;
}
}
byte[] tempByte3 = new byte[packLen];
Array.Copy(tempBuffer, index + 1, tempByte3, 0, packLen);
packageList.Add(tempByte3);
recLen = recLen - packLenLeft;
byte[] tempByte4 = new byte[recLen];
Array.Copy(realByte, packLenLeft, tempByte4, 0, recLen);
realByte = new byte[recLen];
Array.Copy(tempByte4, 0, realByte, 0, tempByte4.Length);
tempBuffer = new byte[1024];
//更改状态
state = true;
}
//触发客户端事件
if (PackageCompleted != null)
{
PackageCompleted();
}
}
else
{
//剩下的小于我们需要的长度,不能取得完整包
//缓冲
int tempIndex = GetRealByte(tempBuffer).Length;
//将剩下的包放到缓冲区中
//Array.Copy(realByte, sepIndex + 1, tempBuffer, tempIndex, recLen);
//Array.Copy(realByte, 0, tempBuffer, tempIndex, recLen);
Array.Copy(realByte, 0, tempBuffer, tempIndex, realByte.Length);
packLenLeft = packLenLeft - recLen;
recLen = 0;
//更改状态
state = false;
}
}
}
}
}
http://www.codeproject.com/Articles/31018/Synchronous-Web-Service-Calls-with-Silverlight-Dis