c# socket select 模型代码(u3d)
其实写过多次网络链接。但是因为换了工作,又没电脑在身边,所以以前的代码都没办法翻出来用。
所以从今天起,一些常用的代码只好放到网上。
公司有一个局域网的游戏。本来想用u3d的rpc就可以完成。但是后来说要传语音。于是只有写一个tcp。
目前完成的模块大的说就两块,网络和消息分发。
服务器有玩家池的管理。
网络部分没有想得很详细。因为是局域网,所以也不存在多大开销。如果有需要上千的需求,可能还要优化下代码结构以及锁。
有缘之人自取。
无论你干什么,我都没任何要求。唯一的要求,如果你发现有bug,或者什么地方改改更好,请告诉我。谢谢!
socket部分
using System.Net.Sockets;
using System.Net;
using System.Threading;
using UnityEngine;
using System.Collections.Generic;
/*
*轻量级局域网服务器。
* 协议如下
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class ClientConnect
{
public byte[] m_AllData;
public int m_AllDataHead;
public int m_AllDataEnd;
public int m_MsgCount;
public byte[] m_OnePack;
public int m_OnePackIndex;
public Socket m_Connect;
public long m_UserID; public ClientConnect()
{
m_AllData = new byte[LanSocketBase.m_MaxAllBuff];
m_AllDataHead = ;
m_AllDataEnd = ;
m_MsgCount = ;
m_OnePack = new byte[LanSocketBase.m_MaxOnePackBuff];
m_OnePackIndex = ;
m_Connect = null;
m_UserID = ;
} public void Reset()
{
m_AllDataHead = ;
m_AllDataEnd = ;
m_MsgCount = ;
m_OnePackIndex = ;
m_Connect = null;
m_UserID = ;
}
}
class Server : LanSocketBase
{
static Queue<int> m_MsgOrder; static Socket m_ServerSocket;
static Thread m_LinstenThread;
static Thread m_ReciveThread;
static System.Collections.ArrayList m_ServerSocketList;
static System.Collections.ArrayList m_listenSocketList;
static System.Collections.ArrayList m_DeleteSocketList;
static int m_MaxClientConnect = ;
static ClientConnect[] m_ConnectPool;
static Queue<int> m_EmptyConnect;
public static void Start()
{
if (m_HasInit)
{
return;
}
string mLocalIP = ""; string mHostName = Dns.GetHostName();
IPHostEntry localHost = Dns.GetHostEntry(mHostName);
for (int i = ; i < localHost.AddressList.Length; ++i)
{
if (localHost.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
MonoBehaviour.print(localHost.AddressList[i].ToString());
mLocalIP = localHost.AddressList[i].ToString();
break;
}
} if ("".Equals(mLocalIP))
{
MonoBehaviour.print("网络检测异常。请检查网络设置或接入网络");
return;
}
LanSocketBase.BaseInit();
m_MsgOrder = new Queue<int>(); //服务器IP地址
IPAddress ip = IPAddress.Parse(mLocalIP);
m_ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ServerSocket.Bind(new IPEndPoint(ip, )); //绑定IP地址:端口
m_ServerSocket.Listen(); //设定最多10个排队连接请求
MonoBehaviour.print("启动监听" + m_ServerSocket.LocalEndPoint.ToString() + "成功"); m_ServerSocketList = new System.Collections.ArrayList();
m_listenSocketList = new System.Collections.ArrayList();
m_DeleteSocketList = new System.Collections.ArrayList(); m_ConnectPool = new ClientConnect[m_MaxClientConnect];
m_EmptyConnect = new Queue<int>();
for (int i = ; i < m_MaxClientConnect; ++i)
{
m_ConnectPool[i] = new ClientConnect();
m_EmptyConnect.Enqueue(i);
}
//通过Clientsoket发送数据
m_ReciveThread = new Thread(ReceiveMessage);
m_ReciveThread.Start();
m_LinstenThread = new Thread(ListenClientConnect);
m_LinstenThread.Start();
} /// <summary>
/// 监听客户端连接
/// </summary>
public static void ListenClientConnect()
{
while (true)
{
Thread.Sleep();
m_ServerSocketList.Add(m_ServerSocket);
Socket.Select(m_ServerSocketList, null, null, );
for (int i = ; i < m_ServerSocketList.Count; ++i)
{
Socket clientSocket = ((Socket)m_ServerSocketList[i]).Accept();
if (null != clientSocket)
{
try
{
Lock();
if ( == m_EmptyConnect.Count)
{
MonoBehaviour.print("链接已经达到最大上线,丢弃当前连接");
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
else
{
//m_listenSocketList.Add(clientSocket);
int mSlot = m_EmptyConnect.Dequeue();
m_ConnectPool[mSlot].m_Connect = clientSocket;
m_ConnectPool[mSlot].m_UserID = System.DateTime.Now.ToFileTime();
MonoBehaviour.print("成功连接一个客户端,编号:" + mSlot.ToString());
}
}
finally
{
UnLock();
}
}
}
m_ServerSocketList.Clear();
}
} private static bool PutDataToBuff(byte[] mClientSendBuff, int mReceiveNumber, Socket client)
{
ClientConnect curPlayer = null;
int mSlot = -;
for (int i = ; i < m_MaxClientConnect; ++i)
{
if (client == m_ConnectPool[i].m_Connect)
{
curPlayer = m_ConnectPool[i];
mSlot = i;
break;
}
}
if (null == curPlayer)
{
return false;
}
if (curPlayer.m_AllDataEnd + mReceiveNumber >= LanSocketBase.m_MaxAllBuff)
{
byte[] mCurAllData = new byte[curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead];
System.Buffer.BlockCopy(curPlayer.m_AllData, curPlayer.m_AllDataHead, mCurAllData, , curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
System.Buffer.BlockCopy(mCurAllData, , curPlayer.m_AllData, , curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
curPlayer.m_AllDataEnd -= curPlayer.m_AllDataHead;
curPlayer.m_AllDataHead = ;
}
int mOnePackStartPos = ;
while (mReceiveNumber > )
{
if ( == m_OnePackIndex)
{
ushort datalen = System.BitConverter.ToUInt16(mClientSendBuff, mOnePackStartPos);
if (datalen > LanSocketBase.m_MaxOnePackBuff || datalen < LanSocketBase.m_HeadSize)
{
return false;
}
if (datalen <= mReceiveNumber)
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
curPlayer.m_AllDataEnd += datalen;
mOnePackStartPos += datalen; mReceiveNumber -= datalen; m_MsgOrder.Enqueue(mSlot);
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
else
{
ushort datalen = System.BitConverter.ToUInt16(m_OnePack, );
if (datalen > LanSocketBase.m_MaxOnePackBuff || datalen < LanSocketBase.m_HeadSize)
{
return false;
}
if (m_OnePackIndex + mReceiveNumber >= datalen)
{
int mNeedNum = datalen - m_OnePackIndex;
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mNeedNum);
mOnePackStartPos += mNeedNum; System.Buffer.BlockCopy(m_OnePack, , curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
m_OnePackIndex = ; mReceiveNumber -= mNeedNum; m_MsgOrder.Enqueue(mSlot);
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
} return true;
} /// <summary>
/// 接收消息
/// </summary>
public static void ReceiveMessage()
{
try
{
while (true)
{
Thread.Sleep();
for (int i = ; i < m_MaxClientConnect; ++i)
{
if (null != m_ConnectPool[i].m_Connect)
{
m_listenSocketList.Add(m_ConnectPool[i].m_Connect);
}
}
if ( == m_listenSocketList.Count)
{
continue;
}
Socket.Select(m_listenSocketList, null, null, );
for (int i = ; i < m_listenSocketList.Count; ++i)
{
Socket mClient = (Socket)m_listenSocketList[i];
//try
//{
//通过clientSocket接收数据
byte[] mClientSendBuff = new byte[m_MaxOnePackBuff];
int mReceiveNumber = mClient.Receive(mClientSendBuff);
if ( == mReceiveNumber)
{
m_DeleteSocketList.Add(mClient);
}
else if (mReceiveNumber > )
{
try
{
Lock();
bool rt = PutDataToBuff(mClientSendBuff, mReceiveNumber, mClient);
if (!rt)
{
m_DeleteSocketList.Add(mClient);
}
}
catch (System.Exception ex)
{
MonoBehaviour.print("PutDataToBuff catch: " + ex.Message);
}
finally
{
UnLock();
}
}
else
{
MonoBehaviour.print("one connect recive a error num: " + mReceiveNumber.ToString());
}
//}
//catch (System.Exception ex)
//{
// MonoBehaviour.print("ReceiveMessage catch: " + ex.Message);
// m_DeleteSocketList.Add(mClient);
//}
}
m_listenSocketList.Clear();
if ( != m_DeleteSocketList.Count)
{
ShutDownConnect();
}
} }
catch (System.Exception ex)
{
MonoBehaviour.print("ReceiveMessage out:" + ex.Message);
} } /// <summary>
/// 程序退出销毁
/// </summary>
public static void Destroy()
{
if (!m_HasInit)
{
return;
}
m_LinstenThread.Abort();
m_ReciveThread.Abort();
m_listenSocketList.Clear(); for (int i = ; i < m_ServerSocketList.Count; ++i)
{
Socket mServer = (Socket)m_ServerSocketList[i];
if (mServer.Connected)
{
mServer.Shutdown(SocketShutdown.Both);
}
mServer.Close();
}
m_ServerSocketList.Clear(); for (int i = ; i < m_MaxClientConnect; ++i)
{
if (null != m_ConnectPool[i].m_Connect)
{
if (m_ConnectPool[i].m_Connect.Connected)
{
m_ConnectPool[i].m_Connect.Shutdown(SocketShutdown.Both);
}
m_ConnectPool[i].m_Connect.Close();
m_ConnectPool[i].m_Connect = null;
}
}
m_EmptyConnect.Clear();
LanSocketBase.BaseRelease();
} /// <summary>
/// 销毁一个连接
/// </summary>
static void ShutDownConnect()
{
try
{
Lock();
for (int j = ; j < m_DeleteSocketList.Count; ++j)
{
Socket connect = (Socket)m_DeleteSocketList[j];
for (int i = ; i < m_MaxClientConnect; ++i)
{
if (connect == m_ConnectPool[i].m_Connect)
{
connect.Shutdown(SocketShutdown.Both);
connect.Close();
m_ConnectPool[i].Reset();
m_EmptyConnect.Enqueue(i);
MonoBehaviour.print("关闭一个连接,编号:" + i.ToString());
break;
}
}
}
}
catch (System.Exception ex)
{
MonoBehaviour.print("ShutDownConnect catch: " + ex.Message);
}
finally
{
m_DeleteSocketList.Clear();
UnLock();
}
} /// <summary>
/// 获取一个数据
/// </summary>
public static void GetMsg(ref ClientMsgUnPack msg)
{
try
{
Lock();
if ( != m_MsgOrder.Count)
{
int mSlot = m_MsgOrder.Dequeue();
ClientConnect curPlayer = m_ConnectPool[mSlot];
ushort mOnePackLen = System.BitConverter.ToUInt16(curPlayer.m_AllData, curPlayer.m_AllDataHead);
msg = new ClientMsgUnPack(curPlayer.m_AllData, (ushort)curPlayer.m_AllDataHead, (ushort)mOnePackLen, mSlot);
msg.SetUserID(curPlayer.m_UserID);
curPlayer.m_AllDataHead += mOnePackLen;
}
}
finally
{
UnLock();
}
} public static void SendTo(ref MsgPack msg, long userID)
{
try
{
Lock();
for(int i = ; i < m_MaxClientConnect ; ++i)
{
ClientConnect curPlayer = m_ConnectPool[i];
if (null != curPlayer.m_Connect && curPlayer.m_UserID == userID)
{
curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
break;
}
}
}
finally
{
UnLock();
}
} public static void SendToAll(ref MsgPack msg)
{
try
{
Lock();
for (int i = ; i < m_MaxClientConnect; ++i)
{
ClientConnect curPlayer = m_ConnectPool[i];
if (null != curPlayer.m_Connect)
{
curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
break;
}
}
}
finally
{
UnLock();
}
}
}
}
SocketServer.cs
using System.Net.Sockets;
using System.Net;
using System.Threading;
using UnityEngine;
using System.Collections.Generic; /*
*轻量级局域网服务器。
* 协议如下
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class Client : LanSocketBase
{
static Thread m_ReciveThread;
static Socket m_Connect;
static byte[] m_AllData;
static int m_AllDataHead;
static int m_AllDataEnd;
static int m_MsgNum; public static void Start()
{
if (m_HasInit)
{
return;
}
//设定服务器IP地址
IPAddress ip = IPAddress.Parse("192.168.1.109");
Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
temp.Connect(new IPEndPoint(ip, )); //配置服务器IP与端口
MonoBehaviour.print("连接服务器成功"); LanSocketBase.BaseInit();
m_Connect = temp;
m_ReciveThread = new Thread(ReceiveMessage);
m_ReciveThread.Start();
m_AllData = new byte[LanSocketBase.m_MaxAllBuff + ];
m_AllDataHead = ;
m_AllDataEnd = ;
m_MsgNum = ;
}
catch
{
MonoBehaviour.print("连接服务器失败");
return;
}
} private static void PutDataToBuff(byte[] mClientSendBuff, int mReceiveNumber)
{
if (m_AllDataEnd + mReceiveNumber >= LanSocketBase.m_MaxAllBuff)
{
byte[] mCurAllData = new byte[m_AllDataEnd - m_AllDataHead];
System.Buffer.BlockCopy(m_AllData, m_AllDataHead, mCurAllData, , m_AllDataEnd - m_AllDataHead);
System.Buffer.BlockCopy(mCurAllData, , m_AllData, , m_AllDataEnd - m_AllDataHead);
m_AllDataEnd -= m_AllDataHead;
m_AllDataHead = ;
}
int mOnePackStartPos = ;
while (mReceiveNumber > )
{
if ( == m_OnePackIndex)
{
ushort datalen = System.BitConverter.ToUInt16(mClientSendBuff, mOnePackStartPos);
if (datalen <= mReceiveNumber)
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_AllData, m_AllDataEnd, datalen);
m_AllDataEnd += datalen; mOnePackStartPos += datalen; mReceiveNumber -= datalen;
++m_MsgNum;
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
else
{
ushort datalen = System.BitConverter.ToUInt16(m_OnePack, );
if (m_OnePackIndex + mReceiveNumber >= datalen)
{
int mNeedNum = datalen - m_OnePackIndex;
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mNeedNum);
mOnePackStartPos += mNeedNum; System.Buffer.BlockCopy(m_OnePack, , m_AllData, m_AllDataEnd, datalen);
m_OnePackIndex = ; mReceiveNumber -= mNeedNum;
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
}
} public static void Destroy()
{
if (!m_HasInit)
{
return;
}
LanSocketBase.BaseRelease();
ShutDownConnect();
m_MsgNum = ;
} public static void GetMsg(ref MsgUnPack msg)
{
if (!m_HasInit)
{
return;
}
try
{
Lock();
if ( != m_MsgNum)
{
ushort datalen = System.BitConverter.ToUInt16(m_AllData, m_AllDataHead);
msg = new MsgUnPack(m_AllData, (ushort)m_AllDataHead, (ushort)datalen);
m_AllDataHead += datalen;
--m_MsgNum;
}
}
finally
{
UnLock();
}
} /// <summary>
/// 接收消息
/// </summary>
public static void ReceiveMessage()
{
while (true)
{
Thread.Sleep();
try
{
//通过clientSocket接收数据
byte[] mClientSendBuff = new byte[m_MaxOnePackBuff + ];
int mReceiveNumber = m_Connect.Receive(mClientSendBuff);
if ( == mReceiveNumber)
{
MonoBehaviour.print("disconnect");
ShutDownConnect();
}
else if (mReceiveNumber > )
{
try
{
Lock();
PutDataToBuff(mClientSendBuff, mReceiveNumber);
}
catch (System.Exception ex)
{
MonoBehaviour.print("PutDataToBuff catch: " + ex.Message);
}
finally
{
UnLock();
}
}
else
{
MonoBehaviour.print("one connect recive a error num: " + mReceiveNumber.ToString());
}
}
catch (System.Exception ex)
{
MonoBehaviour.print("ReceiveMessage catch: " + ex.Message);
ShutDownConnect();
}
}
} public static void Send(ref MsgPack msg)
{
try
{
Lock();
m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
}
finally
{
UnLock();
}
} public static void ShutDownConnect()
{
m_ReciveThread.Abort();
if (m_Connect.Connected)
{
m_Connect.Shutdown(SocketShutdown.Both);
}
m_Connect.Close();
}
}
}
SocketClient.cs
支持类部分
using System.Threading;
using UnityEngine; /*
*轻量级局域网服务器。
* 协议如下
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
public class LanSocketBase
{
public static int m_MaxOnePackBuff = * ;
public static int m_MaxAllBuff = * ;
public static int m_HeadSize = ;
protected static bool m_HasInit = false;
protected static byte[] m_OnePack;
protected static int m_OnePackIndex;
private static Mutex m_Mutex; public static void BaseInit()
{
m_HasInit = true;
m_Mutex = new Mutex();
m_OnePack = new byte[m_MaxOnePackBuff+];
m_OnePackIndex = ;
} public static void BaseRelease()
{
m_Mutex.Close();
} protected static void Lock()
{
m_Mutex.WaitOne();
//MonoBehaviour.print("Lock:" + Thread.CurrentThread.ManagedThreadId.ToString());
} protected static void UnLock()
{
m_Mutex.ReleaseMutex();
//MonoBehaviour.print("Unlock:" + Thread.CurrentThread.ManagedThreadId.ToString());
}
}
}
LanSocketBase
using System.Threading; /*
*轻量级局域网服务器。
* 协议如下
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
public class PackBase
{
protected int m_MaxOnePackBuff;
protected byte[] m_OnePack;
protected int m_OnePackIndex; public PackBase()
{
m_MaxOnePackBuff = LanSocketBase.m_MaxOnePackBuff;
m_OnePack = new byte[m_MaxOnePackBuff];
m_OnePackIndex = ;
}
}
}
PackBase.cs
using UnityEngine;
/*
* 通信协议
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class MsgPack : PackBase
{
public MsgPack()
{
m_OnePackIndex = LanSocketBase.m_HeadSize;
} public void SetHead(int ID)
{
byte[] mBuff = System.BitConverter.GetBytes(ID);
System.Buffer.BlockCopy(mBuff, , m_OnePack, , );
} public void PackEnd()
{
byte[] mBuff = System.BitConverter.GetBytes(m_OnePackIndex);
System.Buffer.BlockCopy(mBuff, , m_OnePack, , );
} public void Packbool(bool data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Packbool() longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
} public void Pack16bit(short data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack16bit(short) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack16bit(ushort data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack16bit(ushort) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack32bit(int data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack32bit(int) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack32bit(uint data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack32bit(uint) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack32bit(float data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack32bit(float) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack64bit(double data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack64bit(double) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
}
public void Pack64bit(long data)
{
ushort curDatalen = ;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("Pack64bit(long) longer lager than Max buff len");
return;
}
byte[] mBuff = System.BitConverter.GetBytes(data);
Pack(mBuff, curDatalen);
} public void PackString(string data, ushort len)
{
ushort curDatalen = len;
if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff)
{
MonoBehaviour.print("PackString() longer lager than Max buff len");
return;
}
byte[] mBuff = System.Text.Encoding.UTF8.GetBytes(data);
Pack(mBuff, curDatalen);
} void Pack(byte[] data, ushort len)
{
System.Buffer.BlockCopy(data, , m_OnePack, m_OnePackIndex, len);
m_OnePackIndex += len;
} public byte[] GetByte()
{
return m_OnePack;
} public int GetByteLen()
{
return m_OnePackIndex;
}
}
}
MsgPack.cs
using UnityEngine;
/*
* 通信协议
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class MsgUnPack : PackBase
{
ushort m_PackLen;
int m_MsgID;
public MsgUnPack()
{
} void GetHead()
{
m_PackLen = System.BitConverter.ToUInt16(m_OnePack, );
m_MsgID = System.BitConverter.ToUInt16(m_OnePack, );
m_OnePackIndex = ;
} public MsgUnPack(byte[] mBuff, ushort len)
{
UnPack(mBuff, len);
} public MsgUnPack(byte[] mBuff, ushort offset, ushort len)
{
UnPack(mBuff, offset, len);
} public void UnPack(byte[] mBuff, ushort len)
{
System.Buffer.BlockCopy(mBuff, , m_OnePack, , len);
GetHead();
} public void UnPack(byte[] mBuff, ushort offset, ushort len)
{
System.Buffer.BlockCopy(mBuff, offset, m_OnePack, , len);
GetHead();
} public bool Readbool()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("Readbool() longer lager than Max buff len");
return false;
}
bool data = System.BitConverter.ToBoolean(m_OnePack, m_OnePackIndex);
++m_OnePackIndex;
return data;
} public short ReadShort()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadShort() longer lager than Max buff len");
return ;
}
short data = System.BitConverter.ToInt16(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public ushort ReadUShort()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadUShortbit() longer lager than Max buff len");
return ;
}
ushort data = System.BitConverter.ToUInt16(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public int ReadInt()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadInt() longer lager than Max buff len");
return ;
}
int data = System.BitConverter.ToInt32(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public uint ReadUInt()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadUInt() longer lager than Max buff len");
return ;
}
uint data = System.BitConverter.ToUInt32(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public float ReadFloat()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadFloat() longer lager than Max buff len");
return 0.0f;
}
float data = System.BitConverter.ToSingle(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public double ReadDouble()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadDouble() longer lager than Max buff len");
return 0.0f;
}
double data = System.BitConverter.ToDouble(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public long ReadLong()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadLong() longer lager than Max buff len");
return ;
}
long data = System.BitConverter.ToInt64(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public ulong ReadULong()
{
if (m_OnePackIndex + > m_PackLen)
{
MonoBehaviour.print("ReadULong() longer lager than Max buff len");
return ;
}
ulong data = System.BitConverter.ToUInt64(m_OnePack, m_OnePackIndex);
m_OnePackIndex += ;
return data;
} public string ReadString(ushort len)
{
if (m_OnePackIndex + len > m_PackLen)
{
MonoBehaviour.print("ReadString() longer lager than Max buff len");
return "";
}
string data = System.Text.Encoding.UTF8.GetString(m_OnePack, m_OnePackIndex, len);
m_OnePackIndex += len;
return data;
} public int GetMsgID()
{
return m_MsgID;
}
}
}
MsgUnPack.cs
using UnityEngine;
/*
* 通信协议
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class ClientMsgUnPack : MsgUnPack
{
long m_UserID;
public ClientMsgUnPack()
{
m_UserID = -;
} public ClientMsgUnPack(byte[] mBuff, ushort len, int userID)
{
m_UserID = userID;
UnPack(mBuff, len);
} public ClientMsgUnPack(byte[] mBuff, ushort offset, ushort len, int userID)
{
m_UserID = userID;
UnPack(mBuff, offset, len);
} public long GetUserID()
{
return m_UserID;
} public void SetUserID(long userID)
{
m_UserID = userID;
}
}
}
ClientMsgUnPack.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic; delegate void EventDelagate(LanSocket.ClientMsgUnPack msg); class EventNode
{
public int m_EventID;
public LanSocket.ClientMsgUnPack msg;
} class EventDispath
{
public static int g_MaxEventNum = ;
List<EventDelagate>[] m_Event;
Queue<EventNode> m_EventQueue;
public EventDispath()
{
m_Event = new List<EventDelagate>[g_MaxEventNum];
m_EventQueue = new Queue<EventNode>();
} public void RegistEvent(int eventID, EventDelagate func)
{
if(null == m_Event[eventID])
{
m_Event[eventID] = new List<EventDelagate>();
}
m_Event[eventID].Add(func);
} public void AddEvent(EventNode eventNode)
{
m_EventQueue.Enqueue(eventNode);
} public void Proccess()
{
if ( != m_EventQueue.Count)
{
EventNode mCur = m_EventQueue.Dequeue();
if (null == m_Event[mCur.m_EventID])
{
MonoBehaviour.print("event ID: "+ mCur.m_EventID+" is null");
}
else
{
List<EventDelagate> curEventDelagate = m_Event[mCur.m_EventID];
for(int i = ; i < curEventDelagate.Count ; ++i)
{
curEventDelagate[i](mCur.msg);
}
}
}
}
}
EventDispath.cs
unity部分
using UnityEngine;
using System.Collections; public class ServerMain : MonoBehaviour
{
bool m_Destroy;
EventDispath m_ClientMsg;
void Start ()
{
m_Destroy = false;
//服务器IP地址
LanSocket.Server.Start();
m_ClientMsg = new EventDispath();
m_ClientMsg.RegistEvent(, Action_123); } // Update is called once per frame
void Update ()
{
if(!m_Destroy)
{
LanSocket.ClientMsgUnPack clientMsg = null;
LanSocket.Server.GetMsg(ref clientMsg);
if (null != clientMsg)
{
print("Msg:" + clientMsg.GetMsgID() + " from: " + clientMsg.GetUserID()); EventNode mNode = new EventNode();
mNode.m_EventID = clientMsg.GetMsgID(); ;
mNode.msg = clientMsg;
m_ClientMsg.AddEvent(mNode);
} m_ClientMsg.Proccess();
}
} void OnDestroy()
{
m_Destroy = true;
LanSocket.Server.Destroy();
} void Action_123(LanSocket.ClientMsgUnPack msg)
{
long userID = msg.GetUserID();
ushort accountLen = msg.ReadUShort();
string account = msg.ReadString(accountLen);
ushort passLen = msg.ReadUShort();
string pass = msg.ReadString(passLen); print("Action_123 account: " + account + " pass word: " + pass+" from user: " + userID); LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
sendMsg.SetHead();
string strAccount = "test account";
sendMsg.Pack16bit((ushort)strAccount.Length);
sendMsg.PackString(strAccount, (ushort)strAccount.Length);
string strPass = "test pass word";
sendMsg.Pack16bit((ushort)strPass.Length);
sendMsg.PackString(strPass, (ushort)strPass.Length);
sendMsg.PackEnd();
LanSocket.Server.SendTo(ref sendMsg, msg.GetUserID());
}
}
ServerMain.cs
using UnityEngine;
using System.Collections; public class ClientMain : MonoBehaviour { // Use this for initialization
void Start ()
{
LanSocket.Client.Start();
} // Update is called once per frame
void Update ()
{
LanSocket.MsgUnPack msg = null;
LanSocket.Client.GetMsg(ref msg);
if(null != msg)
{
print("here have one msg on client");
} if(Input.GetKeyUp(KeyCode.J))
{
LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
sendMsg.SetHead();
string strAccount = "test account";
sendMsg.Pack16bit((ushort)strAccount.Length);
sendMsg.PackString(strAccount, (ushort)strAccount.Length);
string strPass = "test pass word";
sendMsg.Pack16bit((ushort)strPass.Length);
sendMsg.PackString(strPass, (ushort)strPass.Length);
sendMsg.PackEnd();
LanSocket.Client.Send(ref sendMsg);
}
}
void OnDestroy()
{
LanSocket.Client.Destroy();
}
}
ClientMain.cs
以上为全部代码,拖到u3d项目中,然后将clientmain或servermain挂在对象上就可以运行了
c# socket select 模型代码(u3d)的更多相关文章
- u3d局域网游戏网络(c# socket select 模型)
之前写了一篇. 发完之后第二天实际应用到游戏之后还是发现了一些小毛病. 比如网络模块有重复使用(多对象)的情况.所以将静态类该成了普通类. 比如安卓下会有些异常出现导致游戏逻辑不正常.所以网络相关的函 ...
- u3d局域网游戏网络(c# socket select 模型)——续
原文:http://www.cnblogs.com/saucerman/p/5555793.html 因为项目要加语音.语音数据都非常大.所以顺带就把之前写的网络模块一起测试了. 然后发现了一些bug ...
- socket select模型
由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不 ...
- socket select()模型
转载:http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html 由于socket recv()方法是阻塞式的,当有多 ...
- C# Socket select模型
http://www.cnblogs.com/Clingingboy/archive/2011/07/04/2097806.html http://www.cnblogs.com/RascallySn ...
- 多路复用I/O模型select() 模型 代码实现
多路复用I/O: socket编程之select(),poll(),epoll() 代码: client.c #include <stdio.h> #include <sys/ty ...
- windows socket编程select模型使用
int select( int nfds, //忽略 fd_ser* readfds, //指向一个套接字集合,用来检测其可读性 ...
- socket编程的select模型
在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...
- socket之 select模型
前段时间一直想学习网络编程的select模型,看了<windows网络编程>的介绍,参考了别人的博客. 这里的资料主要来自http://www.cnblogs.com/RascallySn ...
随机推荐
- python正则表达式函数match()和search()的区别详解
match()和search()都是python中的正则匹配函数,那这两个函数有何区别呢? match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找 ...
- A+B 输入输出练习I
while True: try: s=raw_input() a,b=s.split(' ') a,b=int(a),int(b) print a+b except EOFError: break A ...
- Css入门课程 Css文本样式
文字是网页的非常基础的内容,文本的样式设置也是非常重要的 1 字体大小 font-size:绝对大小单位和相对大小单位,绝对大小单位有cm,mm in(厘米,毫米,英寸)等,这是大小不随屏幕分辨率大小 ...
- LR脚本编写时的几个小技巧
参数化空值 如上图所示,当参数化时某个值需要为空值(非空格),直接在参数化文件中空一行/格即可,虽然Parameter List界面上没有显示空的那一行,但并不影响取值. 手工日志跟踪 lr_set_ ...
- idea dubbo jar error:cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 'dubbo:application' 的声明
声明: 出现这个错误的情形是,在idea开发环境里面运行是没有问题的,使用哦idea自带的打包工具生成jar之后,运行jar的时候报的这个错误,如果不是这个情况,这篇文章可能不适用. 主要的原因是sp ...
- 【Redis】- 双写一致性
首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作. 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者 ...
- oracle 9i 图文安装教程 oracle 9i 安装
我的安装文件是ISO镜像文件,使用Virtual DAEMON Manager v 4.10打开: ora9i-1.iso ora9i-2.iso ora9i-3.iso 首先必须把上面三个镜像文件都 ...
- QT分析之QApplication的初始化
原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/ 在开始分析之前交代一下,一是分析的QT在Window平台实现 ...
- 使用Xcode进行调试
目录 知己知彼 百战不殆抽刀断Bug 普通操作 全局断点(Global BreakPoint) 条件断点(Condational Breakpoints)打印的艺术 NSLog 开启僵尸对象(Enab ...
- Go语言【第十三篇】:Go语言递归函数
Go语言递归函数 递归,就是在运行的过程中调用自己,语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recurs ...