Unity3D socket
来源:互联网 发布:张国荣爱情知乎 编辑:程序博客网 时间:2024/06/05 05:33
1年前的unity3D项目里面之封装了引擎层。完全没涉及到服务器收发。
最近继续深入u3d了。打算弄个框架。自然这个socket要我自己写了。花了1天的时间大概写好了。自己写了一个服务器一个客户端测了一下。
还不错。哈哈哈。
废话不说上代码.
使用双线程收发。这里有个取巧。
我在每帧更新之前。在主线程调用收线程的数据。
在每帧更新之后。在主线程发送数据到发线程。
这样我收和发的过程中不用锁。哈哈。完全不影响主线程。
虽然我是为客户端写的。但是还是考虑了极限情况。比如一次收到太多消息。导致一个缓冲区不够。我用一个链表后背缓冲区持续不断的收。
一次性做成包。主线程去拿。基本上可以当服务器用了。客户端可不会有这么恶心的情况。导致64k缓冲区都不够,那只能是服务器
主程有点二了。
一样的还是不能在收发线程里面做任何有关u3DAPI的调用。这二的。。
上类
netrecevice
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Xml.Xsl;
using System.IO;
using System.Threading;
namespace Lusuo
{
public class NetRecevice : NetBase
{
public NetRecevice(Socket sock,uint uSize)
: base("recevice", sock, uSize)
{
m_stream = new LusuoStream(new byte[uSize]);
}
public override void Stop()
{
base.Stop();
m_stream.Close();
for (int i = 0; i < m_listBackStream.Count; i ++ )
{
m_listBackStream[i].Close();
}
}
public override void SubWork()
{
if (!m_socket.Connected)
{
//接收线程不能等待。因为没人去激活它
Thread.Sleep(15);
return;
}
ReceiveMessage();
//接收完了。转换成消息等待前台拿
GetReceviceToMsg();
//接受完了休息指定帧数默认60帧
Thread.Sleep(15);
}
//
private void ReceiveMessage()
{
LusuoStream stream = __ReceviceMessage(ref m_stream);
while (null != stream)
{
stream = __ReceviceMessage(ref stream);
}
m_stream.Reset();
}
private LusuoStream __ReceviceMessage(ref LusuoStream lf)
{
//先用基本缓冲读一次
int iLen = 0;
try
{
iLen = m_socket.Receive(lf.GetBuffer(), (int)m_uBufferSize, SocketFlags.None);
if (iLen <= 0)
{
return null;
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
//说明都读不完
if (iLen >= m_uBufferSize)
{
__GenMsg();
//还没有读完
//用新的流继续读
//把没有读完的数据写过来
LusuoStream back = new LusuoStream(new byte[m_uBufferSize]);
byte[] lastbyte = new byte[lf.GetRest()];
lf.Read(ref lastbyte, lf.GetRest());
back.Write(ref lastbyte, lastbyte.Length);
//以后可以利用这个优化
m_listBackStream.Add(back);
return back;
}
else
{
//基本缓冲可以读完
while (iLen > lf.GetOffset())
{
if (-2 == __GenMsg(ref lf))
{
//断开因为有消息不认识了。说明客户端有问题了
//Stop();
}
}
return null;
}
}
private void __GenMsg()
{
//int iMinSize = StringHelper.s_IntSize + StringHelper.s_ShortSize;
//基本流读完了
while (__GenMsg(ref m_stream) != -1) { }
}
private int __GenMsg(ref LusuoStream lf)
{
//如果不够读出一份完整数据。回读
int iMinSize = StringHelper.s_IntSize + StringHelper.s_ShortSize;
if (m_uBufferSize - lf.GetOffset() < iMinSize)
{
return -1;
}
uint uID = 0;
ushort uLen = 0;
lf.ReadUInt(ref uID);
lf.ReadUShort(ref uLen);
//如果不够读一次了
if (m_uBufferSize - (ushort)lf.GetOffset() < uLen)
{
//返回
lf.Seek(lf.GetOffset() - iMinSize);
return -1;
}
//
NetManager netMgr =
(NetManager)SingletonManager.GetSingletonManager().GetSingleton(ref Singleton.s_NetMessage);
NetMessage msg = netMgr.CreateNetMessage(uID);
if(null == msg)
{
Console.WriteLine("未知的消息" + uID.ToString());
//客户端被修改
return -2;
}
msg.m_uDataLenght = uLen;
msg.FromByte(ref lf);
m_listDelegates.Add(msg);
return (int)m_uBufferSize - lf.GetOffset();
}
//得到接收的消息
private void GetReceviceToMsg()
{
m_Lock.WaitOne();
foreach (NetMessage msg in m_listDelegates)
{
m_listMsg.Add(msg);
}
m_listDelegates.Clear();
m_Lock.ReleaseMutex();
//新申请的内存用完了。
for (int i = 0; i < m_listBackStream.Count; i++)
{
m_listBackStream[i].Close();
}
m_listBackStream.Clear();
}
public void GetReceviceMsg(ref List<NetMessage> listMsg)
{
if (m_listMsg.Count == 0)
{
return;
}
m_Lock.WaitOne();
foreach (NetMessage msg in m_listMsg)
{
listMsg.Add(msg);
}
m_listMsg.Clear();
m_Lock.ReleaseMutex();
}
protected LusuoStream m_stream = null;
protected List<LusuoStream> m_listBackStream = new List<LusuoStream>();
}
netsend
public class NetSend : NetBase
{
public NetSend(Socket sock, uint uSize)
: base("send", sock, uSize)
{
m_stream = new LusuoStream(new byte[uSize]);
}
public override void Stop()
{
base.Stop();
m_stream.Close();
}
public override void SubWork()
{
if (!m_socket.Connected)
{
Suspend();
return;
}
//如果还没有建立连接试着建立连接
int iMsgNums = MakeBuffer(ref m_stream);
if (iMsgNums > 0)
{
try
{
int iLen = m_socket.Send(m_stream.GetBuffer(), 0, m_stream.GetOffset(), SocketFlags.None);
if (iLen <= 0)
{
Console.WriteLine("impossiable");
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
m_stream.Reset();
}
//发送完了挂起
Suspend();
}
public void SendMessage(ref List<NetMessage> listMsg)
{
if (listMsg.Count == 0)
{
return;
}
m_Lock.WaitOne();
foreach(NetMessage msg in listMsg)
{
m_listMsg.Add(msg);
}
m_Lock.ReleaseMutex();
if (m_listMsg.Count > 0)
{
Resume();
}
}
public int MakeBuffer(ref LusuoStream lf)
{
if (m_listMsg.Count > 0)
{
m_Lock.WaitOne();
foreach (NetMessage msg in m_listMsg)
{
m_listDelegates.Add(msg);
}
m_listMsg.Clear();
m_Lock.ReleaseMutex();
}
if (m_listDelegates.Count > 0)
{
return __MakeBuffer(ref lf);
}
return 0;
}
private int __MakeBuffer(ref LusuoStream lf)
{
int iFreeBuffer = (int)m_uBufferSize;
int i = 0;
for (; i < m_listDelegates.Count; i++)
{
m_listDelegates[i].MakeMessage();
//不够了。下帧再发
if (iFreeBuffer - m_listDelegates[i].m_uMsgLenght <= 0)
{
//TODO:以后扩展为可以支持任意大小的缓冲
//Debug.LogWarning("消息缓冲区不够了。消息" + m_listDelegates[i].m_uID.ToString() + "隔帧发送");
}
else
{
iFreeBuffer -= m_listDelegates[i].ToByte(ref lf);
}
}
if (i < m_listDelegates.Count)
{
m_listDelegates.RemoveRange(0, i);
}
else
{
m_listDelegates.Clear();
}
return i;
}
protected LusuoStream m_stream = null;
}
}
- Unity3D socket
- Unity3D中的Socket通信
- Unity3D教程:学习Socket
- Unity3d网络游戏Socket通讯
- Unity3D的Socket連線實作範例
- Unity3d网络游戏Socket通讯
- unity3d socket编程案例
- Unity3D的Socket通信
- Unity3D入门Socket初探
- Unity3d网络游戏Socket通讯
- Unity3D Socket通信 UDP
- Unity3D Socket通信 TCP
- Unity3d socket和java socket通信
- Unity3d基于Socket通讯例子
- Unity3d使用socket传输图片
- Unity3d之Socket UDP协议
- Unity3D 使用异步socket通讯
- Unity3d基于Socket通讯例子
- 体验在终端——参加2012年移动开发者大会有感
- wpf路由事件
- 硬盘分区原理及操作系统启动过程(总结自鸟哥Linux私房菜)
- javascript控制table的style属性
- 哈夫曼编码简介
- Unity3D socket
- RAID入门一页通,最全的RAID技术、原理在线图解
- C#--第八周实验--任务5和7--实验DateTime类和TimeSpan类,并实验string类各种方法
- SVM入门
- 【OpenCV】SIFT原理与源码分析:方向赋值
- private static int num=0;
- 360图书馆破解代码
- C语言吧
- raid原理介绍