110,546
社区成员
发帖
与我相关
我的任务
分享
/// <summary>
/// 接收数据包方法
/// </summary>
private void ReceivePacketData()
{
this._scoket.BeginReceive(dataBuff, 0, dataBuff.Length, SocketFlags.None,
new AsyncCallback(ReceiveDataCallback), this);
}
/// <summary>
/// 处理数据包接收回发函数
/// </summary>
/// <param name="ar">上下文对象</param>
private void ReceiveDataCallback(IAsyncResult ar)
{
ClntState cs = (ClntState)ar.AsyncState;
int recvCount = cs._scoket.EndReceive(ar, out errorCode);
if (recvCount <= 0)//这时候应该客户端关闭连接了,一般=0
{
//客户关闭连接
Console.WriteLine("客户端关闭或断开连接!");
if (this.DisConnected != null)
{ DisConnected(this, new NetEventArgs("客户关闭连接!")); }
return;
}
if (errorCode == SocketError.Success)
{
ringMem.Write(dataBuff, 0, dataBuff.Length);
th_readRinMem = new Thread(new ThreadStart(ReadPacket));
th_readRinMem.Start();
//ReadPacket();
}
else
{
if (this.DisConnected != null)
{ DisConnected(this, new NetEventArgs("接收数据失败!!!")); }
}
//重新接收包信息
ReceivePacketData();
}
/// <summary>
/// 读取包信息线程入口
/// </summary>
private void ReadPacket()
{
int leftSize = headerBuff.Length; //剩余数据包头长度
while (true) //为了保证数据完整,这里循环读取,一般一次性能读完
{
leftSize -= this.ringMem.Read(headerBuff, 0, headerBuff.Length);//读取信息头 可能要循环读取
if (leftSize <= 0)
{ break; }
}
//处理头包 并开始接收信息体
currentheader = (PacketHeaderStruct)SerializeTools.DeserializeFromBytes(headerBuff);
if (curHeader.type > 0 && ringMem != null)
{
if (msgBuff != null)
{ msgBuff = null; } //释放内存
msgBuff = new byte[curHeader.length]; //申请内存
int leftSize1 = msgBuff.Length;
while (true) //为了保证数据完整,这里循环读取,一般一次性能读完
{
leftSize1 -= this.ringMem.Read(msgBuff, 0, msgBuff.Length);//读取信息体 可能要循环读取
if (leftSize <= 0)
{ break; }
}
msgObj = SerializeTools.DeserializeFromBytes(msgBuff);
//信息头,和信息体都接收完毕,开始处理信息体,交给ServSocket处理
if (this.ReceiveData != null)
{
this.ReceiveData(this, new NetEventArgs(msgObj)); //接收到数据由ServSocket进行处理
}
}
else //如果没有信息体,继续接收下个信息头,但是也得调用信息处理
{
if (this.ReceiveData != null)
this.ReceiveData(this, new NetEventArgs("接收到信息"));
//重新接收包信息
ReceivePacketData();
}
}
/// <summary>
/// 格式化后的消息类
/// </summary>
class Message
{
public byte Head;
public Int32 Length;
public byte[] Content;
}
/// <summary>
/// 异步接受数据时的回调方法
/// </summary>
/// <param name="ar"></param>
private void OnReceive(IAsyncResult ar) //
{
Socket clientSocket = (Socket)ar.AsyncState;
int real = clientSocket.EndReceive(ar);
if (DealData(clientSocket, real)) //处理接受到的 byte 数据 注意,此时的数据为byte类型
{
clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);//循环接受数据
}
else //服务器关闭socket
{
UpdateForServerExit(); //更新窗体信息
clientSocket.Close();
}
}
/// <summary>
/// 处理接收到的数据
/// </summary>
/// <param name="client"></param>
/// <param name="real"></param>
/// <returns></returns>
private bool DealData(Socket client, int real) //处理接受到的byte类型的数据
{
messageStream.Write(recvBuffer, 0, real);//先将接受到的字节流 写入messageStream缓冲区 这儿是调用Write的地方~~~~~~~~~~~~~~~~~~~~~~~~~~
Message msg = new Message();
while (messageStream.ReadMessage(out msg)) //循环读取消息 调用ReadMessage的地方~~~~~~~~~~~
{
switch (msg.Head) //消息类型
{
case 0: //消息类型为 0
{
// 调用相应 消息处理 函数
break;
}
case 1: //消息类型为 1
{
//调用相应 消息处理 函数
break;
}
case 2: // 消息类型为3
{
//调用相应 消息处理 函数
break;
}
//...............
}
if (msg.Head == 0) //如果服务器端关闭socket(消息类型为 0),那么就返回false
{
return false;
}
}
return true;//对方没有关闭socket,返回true
}