您的位置:首页 > 其它

异步Socket服务器及客户端

2007-05-17 15:41 204 查看
using System;
using System.IO;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;

namespace SocketServer
{
/// <summary>
/// 网络通讯事件模型委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e">与客户端的连接类</param>
public delegate void NetEvent(object sender, TcpTranslate e);

/// <summary>
/// 监听端口,接受多客户的TCP连接
/// </summary>
public class TcpServer
{
#region 事件定义
/// <summary>
/// 接收客户端连接事件
/// </summary>
public event NetEvent Connected;
/// <summary>
/// 与客户端连接断开事件
/// </summary>
public event NetEvent DisConnect;
#endregion

#region 字段
private int maxsockets = 10000; //最大客户连接数
private IPEndPoint iep; //监听终结点
private TcpListener listener; //监听类
private Dictionary<EndPoint, TcpTranslate> session;
#endregion

#region 属性
/// <summary>
/// 当前客户连接数
/// </summary>
public int ConnectCount
{
get { return session.Count; }
}
/// <summary>
/// 与客户连接的所有Socket
/// </summary>
public Dictionary<EndPoint, TcpTranslate> Session
{
get { return session; }
}
#endregion

#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="port">监听的端口号</param>
/// <param name="maxsocket">最大客户连接量</param>
public TcpServer(int maxsockets, string IP, int port)
{
this.maxsockets = maxsockets;
iep = new IPEndPoint(IPAddress.Parse(IP), port);
}
public TcpServer(int port)
{
iep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port);
}
#endregion

#region 公用方法
/// <summary>
/// 启动服务器程序,开始监听客户端请求
/// </summary>
public void Start()
{
session = new Dictionary<EndPoint, TcpTranslate>();
listener = new TcpListener(iep);
listener.Start(10);
//监听客户端连接请求
listener.BeginAcceptSocket(
new AsyncCallback(clientConnect), listener);
}
private void clientConnect(IAsyncResult ar)
{
//接受客户的连接,得连接Socket
Socket socket = listener.EndAcceptSocket(ar);
TcpTranslate trans = new TcpTranslate(socket);
//trans.DisConnect += new NetEvent(trans_DisConnect);
//开始接受数据
trans.StartReceive();

//客户端连接成功事件
if (Connected != null) Connected(this, trans);
TcpTranslate.WriteLine(trans.RemoteEndPoint.ToString() + " is Connection...Num" + session.Count.ToString());
if (session.ContainsKey(trans.RemoteEndPoint))
{
session[trans.RemoteEndPoint] = trans;
}
else
{
session.Add(trans.RemoteEndPoint, trans);
}
if (ConnectCount < maxsockets)
{
//继续监听客户端连接请求
listener.BeginAcceptSocket(
new AsyncCallback(clientConnect), listener);
}
else
{ //达到最大连接客户数,则关闭监听.
listener.Stop();
}
}

//客户端断开连接
void trans_DisConnect(object sender, Socket e)
{
//如果已关闭侦听器,则打开,继续监听
TcpTranslate trans = (TcpTranslate)sender;
if (ConnectCount == maxsockets)
{
listener.Start(1);
listener.BeginAcceptSocket(
new AsyncCallback(clientConnect), listener);
}
session.Remove(trans.RemoteEndPoint);
//触发客户断开事件
if (DisConnect != null) { DisConnect(this, trans); }
TcpTranslate.WriteLine(trans.RemoteEndPoint.ToString() + " is DisConnect...Num" + session.Count.ToString());
}
#endregion
}

#region 传输对象类
/// <summary>
/// 传输对象类,接收缓冲区为默认值 8192 个字节。
/// </summary>
public class TcpTranslate
{
#region 网络事件
/// <summary>
/// 连接成功事件
/// </summary>
public event NetEvent Connect;
/// <summary>
/// 断开连接事件
/// </summary>
public event NetEvent DisConnect;
/// <summary>
/// 接收到数据事件
/// </summary>
public event NetEvent Receive;
/// <summary>
/// 接收到文本事件
/// </summary>
public event NetEvent ReceiveText;
/// <summary>
/// 接收完文件事件
/// </summary>
public event NetEvent ReceiveFile;
/// <summary>
/// 接收完对象事件
/// </summary>
public event NetEvent ReceiveObje;
#endregion

#region 字段
private Socket socket; // 客户连接类
private Stream bufferObject; // 缓存所有接收到的对象数据
private Stream bufferFile; // 缓存所有接收到的文件数据
private int recObjeLen = -1; // 接收到的对象的长度
private int recFileLen = -1; // 接收到的文件的长度
string filePath = @"c:/temp/"; //文件的保存位置
string fileName;
//private List<string> bufferText; // 缓存所有接收到的文本
private IPEndPoint iep;

private bool allowSendText = true;
private bool allowSendObje = true;
private bool allowSendFile = true;
private bool isConnected;

const int bufferLen = 8192; //缓存大小
const int headLen = 4; //包头大小,用于保存要发送数据的总长度
const int headLens = 5; //第一包包头大小
//包头第一个字节,表示此包所包含的内容
readonly byte[] textHead = new byte[] { 0 };//文本
readonly byte[] objeHead = new byte[] { 1 };//对象
readonly byte[] fileHead = new byte[] { 2 };//文件
int receiveBigs; //接收到的包数
//int sendBigs; //发送的包数
#endregion

#region 属性
public EndPoint RemoteEndPoint
{
get { return this.socket.RemoteEndPoint; }
}
public bool Connected
{
get { return this.socket.Connected; }
}
#endregion

#region 构造函数
/// <summary>
/// 服务器端调用此构造函数
/// </summary>
/// <param name="socket">Socket成功连接的Socket</param>
public TcpTranslate(Socket socket)
{
this.socket = socket;
this.socket.ReceiveBufferSize = bufferLen;
this.isConnected = true;
}
/// <summary>
/// 客户端调用此构造函数
/// </summary>
/// <param name="ip">要连接的服务器IP</param>
/// <param name="port">要连接的端口</param>
public TcpTranslate(string ip, int port)
{
iep = new IPEndPoint(IPAddress.Parse(ip), port);
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.socket.ReceiveBufferSize = bufferLen;
this.isConnected = false;
}
#endregion

[System.Diagnostics.Conditional("DUBUG")]
public static void WriteLine(string message)
{
Console.WriteLine(message);
}
/// <summary>
/// 开始接收数据
/// </summary>
public void StartReceive()
{
if (isConnected)
{
byte[] bytes = new byte[bufferLen];
this.socket.BeginReceive(bytes, 0, bufferLen, SocketFlags.None,
new AsyncCallback(ReceivceData), bytes);
}
else
{
this.socket.BeginConnect(iep, new AsyncCallback(connected), socket);
}
}
private void connected(IAsyncResult iar)
{
isConnected = true;
if (Connect != null) Connect(this, this);
byte[] bytes = new byte[bufferLen];
this.socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None,
new AsyncCallback(ReceivceData), bytes);
}

/// <summary>
/// 接收数据回调函数
/// </summary>
/// <param name="ar"></param>
private void ReceivceData(IAsyncResult ar)
{
try
{
//接收到的数据长度.
SocketError sErr;
int receLen = this.socket.EndReceive(ar, out sErr);
if (receLen > 0)
{
byte[] receBytes = (byte[])ar.AsyncState;
switch (receBytes[0])
{
case 0: //接收到文本
ReceivceText(receLen, receBytes);
break;
case 1: //接收到对象
ReceivceObje(receLen, receBytes);
break;
case 2: //接收到文件
ReceivceFile(receLen, receBytes);
break;
default: //接收错误
WriteLine("错误的数据包: 包头为" + receBytes[0].ToString());
WriteLine(sErr.ToString());
break;

}
//继续接收数据
byte[] bytes = new byte[bufferLen];
this.socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None,
new AsyncCallback(ReceivceData), bytes);
return;
}
}
catch (SocketException socketErr)
{
WriteLine(socketErr.Message);
}
catch (ObjectDisposedException socketClose)
{
WriteLine(socketClose.Message);
}
catch (Exception err)
{
WriteLine(err.Message);
}
//断开连接事件
if (DisConnect != null) DisConnect(socket, this);
this.recObjeLen = -1;
this.recFileLen = -1;
}

void ReceivceObje(int receLen, byte[] receBytes)
{
//读第一包.得到本次要接收的数据包的总长
if (recObjeLen == -1 && receLen > headLen)
{
this.recObjeLen = Buffer.Bin2Int(new byte[] {
receBytes[1], receBytes[2], receBytes[3], receBytes[4] });
WriteLine("总长度为:" + recObjeLen.ToString());
this.bufferObject = new MemoryStream();
//不只一包(第一包不为最后一包)
if (this.recObjeLen > bufferLen - headLens)
{
this.bufferObject.Write(receBytes, headLens, receLen - headLens);
}
else
{
this.bufferObject.Write(receBytes, headLens, recObjeLen);
reObjeEnd();
}
}

//最后一包
else if (this.bufferObject.Length + (bufferLen - 1) >= this.recObjeLen)
{
int lastLen = (int)(this.recObjeLen - this.bufferObject.Length);
this.bufferObject.Write(receBytes, 1, lastLen);
reObjeEnd();
}
else
{
this.bufferObject.Write(receBytes, 1, receLen - 1);
//接收到数据事件
if (Receive != null) { Receive(receBytes, this); }
receiveBigs++;
WriteLine(receiveBigs.ToString() + " " + bufferObject.Length.ToString());
}
}
void reObjeEnd()
{
object obj;
lock (bufferObject)
{
this.recObjeLen = -1;
BinaryFormatter formatter = new BinaryFormatter();
bufferObject.Position = 0;
obj = formatter.Deserialize(bufferObject);
}
//接收完数据事件
if (ReceiveObje != null) { ReceiveObje(obj, this); }
WriteLine("对象接收完成 " + obj.GetType().ToString() + " " + obj.ToString());
}
void ReceivceFile(int receLen, byte[] receBytes)
{
//读第一包.得到本次要接收的数据包的总长
if (recFileLen == -1 && receLen > headLen)
{
this.recFileLen = Buffer.Bin2Int(new byte[] {
receBytes[1], receBytes[2], receBytes[3], receBytes[4] });
WriteLine("总长度为:" + recFileLen.ToString());
this.bufferFile = new MemoryStream();
this.bufferFile.Write(receBytes, headLens, receLen - headLens);
do
{
fileName = filePath + DateTime.Now.ToFileTime().ToString();
}
while (File.Exists(this.fileName));
this.bufferFile = File.Create(fileName);

//不只一包
if (this.recFileLen > bufferLen - headLens)
{
this.bufferFile.Write(receBytes, headLens, receLen - headLens);
}
else //第一包为最后一包
{
this.bufferFile.Write(receBytes, headLens, recFileLen);
reFileEnd();
}
}
//最后一包
else if (this.bufferFile.Length + (bufferLen - 1) >= this.recFileLen) //是否最后一包
{
int lastLen = (int)(this.recFileLen - this.bufferFile.Length);
this.bufferFile.Write(receBytes, 1, lastLen);
reFileEnd();
}
else
{
this.bufferFile.Write(receBytes, 1, receLen - 1);
//接收到数据事件
if (Receive != null) { Receive(receBytes, this); }
receiveBigs++;
WriteLine(receiveBigs.ToString() + " " + bufferFile.Length.ToString());
}
}
void reFileEnd()
{
lock (bufferFile)
{
this.recFileLen = -1;
bufferFile.Close();
}
//接收完数据事件
if (ReceiveFile != null) { ReceiveFile(this.fileName, this); }
WriteLine("文件接收完成");
}

void ReceivceText(int receLen, byte[] receBytes)
{
string reStr = Encoding.Default.GetString(receBytes, 1, receLen - 1).TrimEnd('/u0000');
//接收完数据事件
if (ReceiveText != null) { ReceiveText(reStr, this); }
WriteLine(reStr);
}

#region 发送数据
/// <summary>
/// 发送文本
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public bool SendText(string text)
{
if (allowSendText)
{
this.allowSendText = false; //禁止发送文本
Stream stream = new MemoryStream(Encoding.Default.GetBytes(text)); //得到文本的内存流
StateBig stateBig = new StateBig(textHead, stream); //用于格式化流的对象
byte[] bytes = new byte[bufferLen]; //初始化发送包
if (stateBig.GetData(ref bytes) > 0) //向包中填数据
{
this.socket.BeginSend(bytes, 0, bufferLen, SocketFlags.None, //开始异步发送
new AsyncCallback(sendCallback), stateBig);
}
else
{
this.socket.Send(new byte[] { });
this.allowSendText = true;
}
return true;
}
return false;
}
/// <summary>
/// 发送对象
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool SendObject(Object obj)
{
if (allowSendObje)
{
this.allowSendObje = false; //禁止发送对象
Stream stream = Buffer.GetStream(obj); //得到对象的内存流
stream.Position = 0;
StateBig stateBig = new StateBig(objeHead, stream); //用于格式化流的对象
byte[] bytesFrist = new byte[bufferLen - headLen]; //初始化发送包
if (stateBig.GetData(ref bytesFrist) > 0) //向包中填数据
{
byte[] bytes = new byte[bufferLen];
byte[] head = Buffer.Int2Bin((int)stream.Length); //构造包头.包头含有发送的数据的大小
Array.Copy(bytesFrist, 0, bytes, 0, objeHead.Length); //复制文件头标识
Array.Copy(head, 0, bytes, objeHead.Length, headLen); //复制要传送的文件的大小标识
int headLens = objeHead.Length + head.Length;
Array.Copy(bytesFrist, 1, bytes, headLens, bufferLen - headLens); //复制数据
this.socket.BeginSend(bytes, 0, bufferLen, SocketFlags.None, //开始异步发送
new AsyncCallback(sendCallback), stateBig);
}
else
{
this.socket.Send(new byte[] { });
this.allowSendObje = true;
}
return true;
}
return false;
}
/// <summary>
/// 发送文件
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns></returns>
public bool SendFile(string filePath)
{
if (allowSendFile && File.Exists(filePath))
{
this.allowSendFile = false; //禁止发送文件
Stream stream = File.OpenRead(filePath); //得到文件流
stream.Position = 0;
StateBig stateBig = new StateBig(fileHead, stream); //用于格式化流的对象
byte[] bytesFrist = new byte[bufferLen - headLen]; //初始化发送包
if (stateBig.GetData(ref bytesFrist) > 0) //向包中填数据
{
byte[] bytes = new byte[bufferLen];
byte[] head = Buffer.Int2Bin((int)stream.Length); //构造包头.包头含有发送的数据的大小
Array.Copy(bytesFrist, 0, bytes, 0, objeHead.Length); //复制文件头标识
Array.Copy(head, 0, bytes, objeHead.Length, headLen); //复制要传送的文件的大小标识
int headLens = objeHead.Length + head.Length;
Array.Copy(bytesFrist, 1, bytes, headLens, bufferLen - headLens); //复制数据
this.socket.BeginSend(bytes, 0, bufferLen, SocketFlags.None, //开始异步发送
new AsyncCallback(sendCallback), stateBig);
}
else
{
this.socket.Send(new byte[] { });
this.allowSendFile = true;
}
return true;
}
return false;
}

/// <summary>
/// 异步发送回调函数
/// </summary>
/// <param name="ar">包含要发送的数据流及数据包的包头</param>
private void sendCallback(IAsyncResult ar)
{
StateBig stateBig = (StateBig)ar.AsyncState; //得到包含要发送的数据流的对象
int sent = this.socket.EndSend(ar);
byte[] bytes = new byte[bufferLen];
if (stateBig.GetData(ref bytes) > 0)
{
this.socket.BeginSend(bytes, 0, bufferLen, SocketFlags.None,
new AsyncCallback(sendCallback), stateBig);
}
else
{
byte headNum = stateBig.BigHead[0];
switch (headNum)
{
case 0:
this.allowSendText = true; break;
case 1:
this.allowSendObje = true; break;
case 2:
this.allowSendFile = true; break;
default:
break;
}
stateBig.Close();
}
}
#endregion

/// <summary>
/// 从流中读出数据转化为格式化的包.
/// </summary>
public class StateBig
{
private byte[] bigHead;
private Stream stream;
public byte[] BigHead
{
get { return bigHead; }
}
public Stream Stream
{
get { return stream; }
}
public StateBig(byte[] bigHead, Stream stream)
{
this.bigHead = bigHead;
this.stream = stream;
this.stream.Position = 0;
}
~StateBig()
{
this.bigHead = null;
this.stream.Close();
}
public int GetData(ref byte[] bytes)
{
Array.Copy(bigHead, 0, bytes, 0, bigHead.Length);
int readNum = stream.Read(bytes, bigHead.Length, bytes.Length - bigHead.Length);
return readNum;
}
public void Close()
{
this.bigHead = null;
this.stream.Close();
}
}

}
#endregion

#region INT to BIN
public class Buffer
{
/// <summary>
/// 将Int转换为Byte[4]
/// </summary>
public static byte[] Int2Bin(int intNum)
{
byte[] byteNew = new byte[4];
for (byte i = 0; i < 4; i++)
{
byteNew[i] = (byte)(intNum % 256);
intNum = intNum >> 8;
}
return byteNew;
}
/// <summary>
/// 将Byte[4]数组转换为int;
/// </summary>
public static int Bin2Int(byte[] bytes)
{
int intNum = 0;
for (byte i = 0; i < 4; i++)
{
intNum += bytes[i] << (i * 8);
}
return intNum;
}
/// <summary>
/// 将uint转换为Byte[4]
/// </summary>
public static byte[] UInt2Bin(uint uintNum)
{
byte[] byteNew = new byte[4];
for (byte i = 0; i < 4; i++)
{
byteNew[i] = (byte)(uintNum % 256);
uintNum = uintNum >> 8;
}
return byteNew;
}
/// <summary>
/// 将Byte[4]数组转换为uint;
/// </summary>
public static uint Bin2UInt(byte[] bytes)
{
uint uintNum = 0;
for (byte i = 0; i < 4; i++)
{
uintNum += (uint)bytes[i] << (i * 8);
}
return uintNum;
}
public static Stream GetStream(object objData)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream objStrean = new MemoryStream();
formatter.Serialize(objStrean, objData);
return objStrean;
}
#endregion
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐