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 ...
随机推荐
- 深入理解Java对象序列化(转载)
原文地址:http://developer.51cto.com/art/201202/317181.htm 1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般 ...
- Debian常用設置
1. 更新軟件源 sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak #備份 sudo vi /etc/apt/sources.list / ...
- 可用于jquery animate()方法的css属性
* backgroundPosition * borderWidth * borderBottomWidth * borderLeftWidth * borderRightWidth * border ...
- 某一线互联网公司前端面试题js部分总结
js部分 1,使用严格模式的优点 - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全之处,保证代码运行的安全: - 提高编译器效率,增加运行速度 ...
- c++的一些编程技巧和细节
1.函数形参,如: CreateProcess( NULL, cmdbuf, NULL, ...
- dwarf是怎样处理的栈帧?
dwarf是如何处理的栈帧呢? 首先看下非dwarf的情况是如何处理栈帧的: 1 3623804982590 0x3e90 [0xb0]: PERF_RECORD_SAMPLE(IP, 0x1): 1 ...
- Delphi 的绘图功能[8] - TextOut、TextWidth、TextHeight
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...
- Bootstrap 基本模板理解
<!-- 声明文档类型 为 html5 --> <!DOCTYPE html> <!-- 声明页面内容主要为 中文简体 --> <html lang=&quo ...
- BZOJ 1057 棋盘制作(最大01相间子矩阵)
求最大01相间子矩阵可以转换为求最大全0子矩阵.只需把棋盘(x+y)为奇数的取反,而该问题可以用经典的悬线法O(n^2)的求解. 悬线法呢. 首先定义b[i][j],为a[i][j]向上的最大连续0的 ...
- Django Models相关
Models的相关知识 1. AutoField:自增整数类型.根据 ID 自增长的 Int字段 2. IntegerField:整数类型 3. BigIntegerField:大整数类型.用于数值较 ...