u3d局域网游戏网络(c# socket select 模型)——续
原文:http://www.cnblogs.com/saucerman/p/5555793.html
因为项目要加语音。语音数据都非常大。所以顺带就把之前写的网络模块一起测试了。
然后发现了一些bug,逐修。本来想在原文上面直接修改掉。但是恐怕已经看到的人拿去用了之后,再回头看也不一定能看明白,索性再写一文,将新文件直接放上来。
错误修改:
- 网络接收数据后,有一种情况没有处理完整,导致接收数据之后数据池的计数器没有向后偏移
- 网络数据处理后,当当前包仅剩1字节,下一个次数据进来的时候,需要2字节才能确认当前消息长度。增加了消息补齐机制。
- 增加了当网络数据拥堵的时候,直接断开当前链接。
- MsgUnPack的GetHead函数获取消息id的时候使用了错误的函数,导致数据偏移不正确
- MsgUnPack的UnPack(byte[] mBuff, ushort offset, ushort len),由于总buff扩大,导致offset参数超过上限,改为int
- 消息事件增加了错误消息ID过滤
由于语音的需求,将原本的服务器段接受buff容量扩大一倍。增加了语音模块。
特别说下语音模块。
http://blog.csdn.net/huutu/article/details/20216613
这是原文。
稍做修改。特别说一下这个语音模块在使用中容易遇到的问题。
- 如果声音太小,可能是你录音设备的侦听开得不够。
- 本地测试还好,放到网络上之后,因为代码里有处理,如果没有对象会创建对象并且添加必要组件。原文在创建的时候比特率是手动填写的。导致我客户端一个比特率,服务器一个比特率。然后客户端听着一切正常,传给服务器就错了。后来查了一天,排查各个代码段之后才找到这个原因。
以下是代码:
新增语音模块:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Collections; [RequireComponent(typeof(AudioSource))]
public class MicroPhoneInput : MonoBehaviour
{ private static MicroPhoneInput m_instance; public float sensitivity = ;
public float loudness = ; private static string[] micArray = null; const int HEADER_SIZE = ; const int RECORD_TIME = ;
const int RECORD_frequency = ; // Use this for initialization
void Start()
{
} public static MicroPhoneInput getInstance()
{
if (m_instance == null)
{
micArray = Microphone.devices;
if (micArray.Length == )
{
Debug.LogError("Microphone.devices is null");
}
foreach (string deviceStr in Microphone.devices)
{
Debug.Log("device name = " + deviceStr);
}
if (micArray.Length == )
{
Debug.LogError("no mic device");
} GameObject MicObj = new GameObject("MicObj");
m_instance = MicObj.AddComponent<MicroPhoneInput>();
}
return m_instance;
} public void StartRecord()
{
audio.Stop();
if (micArray.Length == )
{
Debug.Log("No Record Device!");
return;
}
audio.loop = false;
audio.mute = true;
audio.clip = Microphone.Start(null, false, RECORD_TIME, RECORD_frequency); //22050
while (!(Microphone.GetPosition(null) > ))
{
}
audio.Play();
Debug.Log("StartRecord");
//倒计时
StartCoroutine(TimeDown()); } public void StopRecord()
{
if (micArray.Length == )
{
Debug.Log("No Record Device!");
return;
}
if (!Microphone.IsRecording(null))
{
return;
}
Microphone.End(null);
audio.Stop(); Debug.Log("StopRecord"); } public Byte[] GetClipData()
{
if (audio.clip == null)
{
Debug.Log("GetClipData audio.clip is null");
return null;
} float[] samples = new float[audio.clip.samples]; audio.clip.GetData(samples, ); Byte[] outData = new byte[samples.Length * ];
//Int16[] intData = new Int16[samples.Length];
//converting in 2 float[] steps to Int16[], //then Int16[] to Byte[] int rescaleFactor = ; //to convert float to Int16 for (int i = ; i < samples.Length; i++)
{
short temshort = (short)(samples[i] * rescaleFactor); Byte[] temdata = System.BitConverter.GetBytes(temshort); outData[i * ] = temdata[];
outData[i * + ] = temdata[]; }
if (outData == null || outData.Length <= )
{
Debug.Log("GetClipData intData is null");
return null;
}
//return intData;
return outData;
}
public void PlayClipData(Int16[] intArr)
{
if (intArr.Length == )
{
Debug.Log("get intarr clipdata is null");
return;
}
//从Int16[]到float[]
float[] samples = new float[intArr.Length];
int rescaleFactor = ;
for (int i = ; i < intArr.Length; i++)
{
samples[i] = (float)intArr[i] / rescaleFactor;
} //从float[]到Clip
AudioSource audioSource = this.GetComponent<AudioSource>();
if (audioSource.clip == null)
{
audioSource.clip = AudioClip.Create("playRecordClip", intArr.Length, , RECORD_frequency, false, false);
}
audioSource.clip.SetData(samples, );
audioSource.mute = false;
audioSource.Play();
}
public void PlayRecord()
{
if (audio.clip == null)
{
Debug.Log("audio.clip=null");
return;
}
audio.mute = false;
audio.loop = false;
audio.Play();
Debug.Log("PlayRecord"); } public float GetAveragedVolume()
{
float[] data = new float[];
float a = ;
audio.GetOutputData(data, );
foreach (float s in data)
{
a += Mathf.Abs(s);
}
return a / ;
} // Update is called once per frame
void Update()
{
// loudness = GetAveragedVolume() * sensitivity;
// if (loudness > 1)
// {
// Debug.Log("loudness = " + loudness);
// }
} private IEnumerator TimeDown()
{
Debug.Log(" IEnumerator TimeDown()"); int time = ;
while (time < RECORD_TIME)
{
if (!Microphone.IsRecording(null))
{ //如果没有录制
Debug.Log("IsRecording false");
yield break;
}
Debug.Log("yield return new WaitForSeconds " + time);
yield return new WaitForSeconds();
time++;
}
if (time >= )
{
Debug.Log("RECORD_TIME is out! stop record!");
StopRecord();
}
yield return ;
}
}
MicroPhoneInput.cs
接下来的都和之前的一样。
using UnityEngine;
/*
* 通信协议
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
class ClientMsgUnPack : MsgUnPack
{
long m_UserID;
public ClientMsgUnPack()
{
m_UserID = -;
} public ClientMsgUnPack(byte[] mBuff, ushort len, long userID)
{
m_UserID = userID;
UnPack(mBuff, len);
} public ClientMsgUnPack(byte[] mBuff, int offset, ushort len, long 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 ServerEventDelagate(LanSocket.ClientMsgUnPack msg); class EventNode
{
public int m_EventID;
public LanSocket.ClientMsgUnPack msg;
} class EventDispathBase
{
public static int g_MaxEventNum = ;
} class ServerEventDispath : EventDispathBase
{
List<ServerEventDelagate>[] m_Event;
Queue<EventNode> m_EventQueue;
public ServerEventDispath()
{
m_Event = new List<ServerEventDelagate>[g_MaxEventNum];
m_EventQueue = new Queue<EventNode>();
} public void RegistEvent(int eventID, ServerEventDelagate func)
{
if(null == m_Event[eventID])
{
m_Event[eventID] = new List<ServerEventDelagate>();
}
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 (mCur.m_EventID >= g_MaxEventNum || mCur.m_EventID < )
{
MonoBehaviour.print("error event ID: " + mCur.m_EventID);
return;
}
if (null == m_Event[mCur.m_EventID])
{
MonoBehaviour.print("event ID: "+ mCur.m_EventID+" is null");
}
else
{
List<ServerEventDelagate> curEventDelagate = m_Event[mCur.m_EventID];
for(int i = ; i < curEventDelagate.Count ; ++i)
{
curEventDelagate[i](mCur.msg);
}
}
}
}
} delegate void ClientEventDelagate(LanSocket.MsgUnPack msg);
class ClientEventDispath : EventDispathBase
{
List<ClientEventDelagate>[] m_Event;
Queue<EventNode> m_EventQueue;
public ClientEventDispath()
{
m_Event = new List<ClientEventDelagate>[g_MaxEventNum];
m_EventQueue = new Queue<EventNode>();
} public void RegistEvent(int eventID, ClientEventDelagate func)
{
if (null == m_Event[eventID])
{
m_Event[eventID] = new List<ClientEventDelagate>();
}
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 (mCur.m_EventID >= g_MaxEventNum || mCur.m_EventID < )
{
MonoBehaviour.print("error event ID: " + mCur.m_EventID);
return;
}
if (null == m_Event[mCur.m_EventID])
{
MonoBehaviour.print("event ID: " + mCur.m_EventID + " is null");
}
else
{
List<ClientEventDelagate> curEventDelagate = m_Event[mCur.m_EventID];
for (int i = ; i < curEventDelagate.Count; ++i)
{
curEventDelagate[i](mCur.msg);
}
}
}
}
}
EventDispath.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 bool m_HasInit = false;
private Mutex m_Mutex; public void BaseInit()
{
m_HasInit = true;
m_Mutex = new Mutex();
} public void BaseRelease()
{
m_Mutex.Close();
} protected void Lock()
{
m_Mutex.WaitOne();
//MonoBehaviour.print("Lock:" + Thread.CurrentThread.ManagedThreadId.ToString());
} protected void UnLock()
{
m_Mutex.ReleaseMutex();
//MonoBehaviour.print("Unlock:" + Thread.CurrentThread.ManagedThreadId.ToString());
}
}
}
LanSocketBase.cs
using UnityEngine;
/*
* 通信协议
* 消息头前2字节保存当前消息长度
* 后面跟4字节表示消息ID
* 再后面是消息实质内容
*/ namespace LanSocket
{
public 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);
} public void PackByte(byte[] data, int offset, ushort len)
{
if (m_OnePackIndex + len > m_MaxOnePackBuff)
{
MonoBehaviour.print("PackByte() longer lager than Max buff len");
return;
}
System.Buffer.BlockCopy(data, offset, m_OnePack, m_OnePackIndex, len);
m_OnePackIndex += len;
} 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.ToInt32(m_OnePack, );
m_OnePackIndex = ;
} public MsgUnPack(byte[] mBuff, ushort len)
{
UnPack(mBuff, len);
} public MsgUnPack(byte[] mBuff, int 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, int 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 byte[] ReadByte(ushort len)
{
byte[] mCur = null;
if (m_OnePackIndex + len > m_PackLen)
{
MonoBehaviour.print("ReadByte() longer lager than Max buff len");
return mCur;
}
mCur = new byte[len];
System.Buffer.BlockCopy(m_OnePack, m_OnePackIndex, mCur, , len);
m_OnePackIndex += len;
return mCur;
} public int GetMsgID()
{
return m_MsgID;
}
}
}
MsgUnPack.cs
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 System.Net.Sockets;
using System.Threading;
using System.Net; public class SocketBase
{
protected bool m_HasInit = false;
protected Socket m_Socket;
protected Thread m_LinstenThread;
protected IPEndPoint m_IP;
protected Mutex m_Mutex;
}
SocketBase.cs
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Collections.Generic; class ReciveBroadcast : SocketBase
{
public Queue<string> m_ServerIP;
public void Start(int port)
{
if (m_HasInit)
{
return;
}
try
{
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_IP = new IPEndPoint(IPAddress.Any, port);
m_Socket.Bind(m_IP);
MonoBehaviour.print("广播网络启动监听" + m_Socket.LocalEndPoint.ToString());
m_LinstenThread = new Thread(ListenClientConnect);
m_LinstenThread.Start();
m_ServerIP = new Queue<string>();
m_Mutex = new Mutex();
m_HasInit = true;
}
catch (System.Exception ex)
{
MonoBehaviour.print("Broadcast reciver Start catch:" + ex.Message);
}
} void ListenClientConnect()
{
EndPoint ep = (EndPoint)m_IP;
try
{
while (true)
{
Thread.Sleep();
byte[] data = new byte[];
int recv = m_Socket.ReceiveFrom(data, ref ep);
string stringData = System.Text.Encoding.UTF8.GetString(data, , recv);
m_Mutex.WaitOne();
m_ServerIP.Enqueue(stringData);
m_Mutex.ReleaseMutex();
MonoBehaviour.print("received: " + stringData + " from: " + ep.ToString());
}
}
catch (System.Exception ex)
{
MonoBehaviour.print("Broadcast reciver ListenClientConnect out:" + ex.Message);
}
} public void Destroy()
{
if (!m_HasInit)
{
return;
}
m_Socket.Close();
m_LinstenThread.Abort();
} public string GetIP()
{
if (!m_HasInit)
{
return "";
} try
{
m_Mutex.WaitOne();
if ( != m_ServerIP.Count)
{
m_Mutex.ReleaseMutex();
return m_ServerIP.Dequeue();
}
m_Mutex.ReleaseMutex();
}
catch (System.Exception ex)
{
MonoBehaviour.print("Broadcast GetIP catch:" + ex.Message);
return "";
}
return "";
}
}
ReciveBroadcast.cs
using UnityEngine;
using System.Net.Sockets;
using System.Net; class SendBroadcast : SocketBase
{
byte[] m_MyIP;
public void Start(int port)
{
if (m_HasInit)
{
return;
}
try
{
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_IP = new IPEndPoint(IPAddress.Broadcast, port);//255.255.255.255
//m_IP = new IPEndPoint(IPAddress.Parse("192.168.255.255"), 9050); string mLocalIP = "";
string hostname = Dns.GetHostName();
IPHostEntry localHost = Dns.GetHostEntry(hostname);
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(m_MyIP))
{
MonoBehaviour.print("网络检测异常。请检查网络设置或接入网络");
m_Socket.Close();
m_Socket = null;
return;
}
m_MyIP = System.Text.Encoding.UTF8.GetBytes(mLocalIP);
m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, );
m_HasInit = true;
}
catch (System.Exception ex)
{
MonoBehaviour.print("Broadcast sender Start catch:" + ex.Message);
}
} public void Send()
{
if(null != m_Socket)
{
MonoBehaviour.print("send a broadcast");
m_Socket.SendTo(m_MyIP, m_IP);
}
} public void Destroy()
{
if (!m_HasInit)
{
return;
}
m_Socket.Close();
}
}
SendBroadcast.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
{
Thread m_ReciveThread;
Socket m_Connect;
byte[] m_AllData;
int m_AllDataHead;
int m_AllDataEnd;
int m_MsgNum;
byte[] m_OnePack;
int m_OnePackIndex; public void Start(string strIP, int port)
{
if (m_HasInit)
{
return;
}
//设定服务器IP地址
IPAddress ip = IPAddress.Parse(strIP);
Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
temp.Connect(new IPEndPoint(ip, port)); //配置服务器IP与端口
MonoBehaviour.print("连接服务器成功"); 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 = ;
m_OnePack = new byte[m_MaxOnePackBuff + ];
m_OnePackIndex = ;
}
catch (System.Exception ex)
{
MonoBehaviour.print("连接服务器失败: " + ex.Message);
return;
}
} private 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
{
if (m_OnePackIndex < )
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, ); ++m_OnePackIndex;
--mReceiveNumber;
++mOnePackStartPos;
}
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 = ;
m_AllDataEnd += datalen; mReceiveNumber -= mNeedNum;
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
}
} public void Destroy()
{
if (!m_HasInit)
{
return;
}
BaseRelease();
ShutDownConnect();
m_MsgNum = ;
} public 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 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 void Send(ref MsgPack msg)
{
try
{
Lock();
m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
}
finally
{
UnLock();
}
} public void ShutDownConnect()
{
m_ReciveThread.Abort();
if (m_Connect.Connected)
{
m_Connect.Shutdown(SocketShutdown.Both);
}
m_Connect.Close();
}
}
}
SocketClient.cs
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
{
Queue<int> m_MsgOrder; Socket m_ServerSocket;
Thread m_LinstenThread;
Thread m_ReciveThread;
System.Collections.ArrayList m_ServerSocketList;
System.Collections.ArrayList m_listenSocketList;
System.Collections.ArrayList m_DeleteSocketList;
int m_MaxClientConnect = ;
ClientConnect[] m_ConnectPool;
Queue<int> m_EmptyConnect;
public void Start(int port)
{
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;
}
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, port)); //绑定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 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 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 = ; if(curPlayer.m_AllDataEnd + mReceiveNumber >= LanSocketBase.m_MaxAllBuff)
{
return false;
}
}
int mOnePackStartPos = ;
while (mReceiveNumber > )
{
if ( == curPlayer.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, curPlayer.m_OnePack, curPlayer.m_OnePackIndex, mReceiveNumber);
curPlayer.m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
else
{
if(curPlayer.m_OnePackIndex < )
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, curPlayer.m_OnePack, curPlayer.m_OnePackIndex, ); ++curPlayer.m_OnePackIndex;
--mReceiveNumber;
++mOnePackStartPos;
}
ushort datalen = System.BitConverter.ToUInt16(curPlayer.m_OnePack, );
if (datalen > LanSocketBase.m_MaxOnePackBuff || datalen < LanSocketBase.m_HeadSize)
{
return false;
}
if (curPlayer.m_OnePackIndex + mReceiveNumber >= datalen)
{
int mNeedNum = datalen - curPlayer.m_OnePackIndex;
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, curPlayer.m_OnePack, curPlayer.m_OnePackIndex, mNeedNum);
mOnePackStartPos += mNeedNum; System.Buffer.BlockCopy(curPlayer.m_OnePack, , curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
curPlayer.m_OnePackIndex = ;
curPlayer.m_AllDataEnd += datalen; mReceiveNumber -= mNeedNum; m_MsgOrder.Enqueue(mSlot);
}
else
{
System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, curPlayer.m_OnePack, curPlayer.m_OnePackIndex, mReceiveNumber);
curPlayer.m_OnePackIndex += mReceiveNumber;
mOnePackStartPos += mReceiveNumber; mReceiveNumber -= mReceiveNumber;
}
}
} return true;
} /// <summary>
/// 接收消息
/// </summary>
public 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 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();
BaseRelease();
} /// <summary>
/// 销毁一个连接
/// </summary>
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 void GetMsg(ref ClientMsgUnPack msg)
{
if(!m_HasInit)
{
return;
}
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, curPlayer.m_AllDataHead, (ushort)mOnePackLen, curPlayer.m_UserID);
curPlayer.m_AllDataHead += mOnePackLen;
}
}
finally
{
UnLock();
}
} public 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 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 UnityEngine;
using System.Collections; public class ClientMain : MonoBehaviour { // Use this for initialization
ClientEventDispath m_Msg;
SendBroadcast m_Sender;
ReciveBroadcast m_Reciver;
LanSocket.Client m_GameNet;
string m_GameServerIP;
bool m_bReady;
float m_BroadTime; void Start ()
{
m_Sender = new SendBroadcast();
m_Sender.Start();
m_Reciver = new ReciveBroadcast();
m_Reciver.Start(); m_GameNet = new LanSocket.Client(); m_GameServerIP = ""; m_bReady = false;
m_BroadTime = 0.0f; EventDispathBase.g_MaxEventNum = (int)NetMsgID.NET_MSG_END;
m_Msg = new ClientEventDispath();
m_Msg.RegistEvent((int)NetMsgID.S2C_SEND_ANIMAL_DATA, Action_S2C_SEND_ANIMAL_DATA);
} void OnGUI()
{
if (GUILayout.Button("Record"))
{
MicroPhoneInput.getInstance().StartRecord();
}
if (GUILayout.Button("End"))
{
MicroPhoneInput.getInstance().StopRecord();
}
if (GUILayout.Button("send"))
{
byte[] data = MicroPhoneInput.getInstance().GetClipData(); LanSocket.MsgPack audioBegin = new LanSocket.MsgPack();
audioBegin.SetHead((int)NetMsgID.C2S_ASK_SEND_AUDIO_BEGIN);
audioBegin.PackEnd();
m_GameNet.Send(ref audioBegin); print("audio length = " + data.Length);
int lastData = data.Length;
int offset = ;
while (true)
{
ushort sendNum = (ushort)lastData;
if (lastData > )
{
sendNum = ;
}
LanSocket.MsgPack audioData = new LanSocket.MsgPack();
audioData.SetHead((int)NetMsgID.C2S_ASK_SEND_AUDIO);
audioData.Pack16bit(sendNum);
audioData.PackByte(data, offset, sendNum);
audioData.PackEnd();
m_GameNet.Send(ref audioData); // string result = string.Empty;
// for (int i = 0; i < sendNum; i++)
// {
// result += System.Convert.ToString(data[offset + i], 16) + " ";
// }
// print(result); offset += sendNum;
if (offset >= data.Length)
{
break;
}
lastData -= sendNum;
}
LanSocket.MsgPack audioEnd = new LanSocket.MsgPack();
audioEnd.SetHead((int)NetMsgID.C2S_ASK_SEND_AUDIO_END);
audioEnd.PackEnd();
m_GameNet.Send(ref audioEnd); // string result2 = string.Empty;
// for (int i = 0; i < data.Length; i++)
// {
// result2 += System.Convert.ToString(data[i], 16) + " ";
// }
// print(result2);
}
if (GUILayout.Button("Play"))
{
MicroPhoneInput.getInstance().PlayRecord();
}
if (GUILayout.Button("PlayByData"))
{
byte[] data = MicroPhoneInput.getInstance().GetClipData();
short[] decodeData = new short[data.Length / ];
for (int i = ; i < decodeData.Length; ++i)
{
decodeData[i] = System.BitConverter.ToInt16(data, i * );
}
MicroPhoneInput.getInstance().PlayClipData(decodeData);
}
} // Update is called once per frame
void Update ()
{
if (m_bReady)
{
LanSocket.MsgUnPack msg = null;
m_GameNet.GetMsg(ref msg);
if (null != msg)
{
print("here have one msg on client");
} if (Input.GetKeyUp(KeyCode.Space))
{
LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
sendMsg.SetHead((int)NetMsgID.C2S_SELECT_ANIMAL);
sendMsg.Pack16bit();
sendMsg.PackEnd();
m_GameNet.Send(ref sendMsg);
print("send 1");
}
}
else
{
m_GameServerIP = m_Reciver.GetIP();
if ("".Equals(m_GameServerIP))
{
m_BroadTime -= Time.deltaTime;
if(m_BroadTime - Time.deltaTime < 0.0f)
{
m_BroadTime = 5.0f;
m_Sender.Send();
}
}
else
{
print("get broadcast ip:" + m_GameServerIP);
GameStart();
}
}
}
void OnDestroy()
{
m_GameNet.Destroy();
if(null != m_Reciver)
{
m_Reciver.Destroy();
}
if (null != m_Sender)
{
m_Sender.Destroy();
}
} void GameStart()
{
m_bReady = true;
m_GameNet.Start(m_GameServerIP, );
try
{
m_Reciver.Destroy();
m_Sender.Destroy();
}
catch (System.Exception ex)
{
MonoBehaviour.print("GameStart catch:" + ex.Message);
}
m_Reciver = null;
m_Reciver = null;
} void Action_S2C_SEND_ANIMAL_DATA(LanSocket.MsgUnPack msg)
{
}
}
ClientMain.cs
using UnityEngine;
using System.Collections; enum NetMsgID
{
NET_MSG_START = ,
S2C_SEND_ANIMAL_DATA,
C2S_SELECT_ANIMAL,
C2S_ASK_SEND_AUDIO_BEGIN,
C2S_ASK_SEND_AUDIO,
C2S_ASK_SEND_AUDIO_END, NET_MSG_END,
}
Common.cs
using UnityEngine;
using System.Collections; public class ServerMain : MonoBehaviour
{
bool m_Destroy;
ServerEventDispath m_ClientMsg;
ReciveBroadcast m_Reciver;
SendBroadcast m_Sender;
LanSocket.Server m_GameNet;
byte[] m_AudioData;
int m_AudioOffset;
int m_AudioLen;
void Start ()
{
m_Destroy = false;
//广播
m_Reciver = new ReciveBroadcast();
m_Reciver.Start();
m_Sender = new SendBroadcast();
m_Sender.Start(); //游戏网络
m_GameNet = new LanSocket.Server();
m_GameNet.Start(); m_AudioData = new byte[];
m_AudioOffset = ;
m_AudioLen = ; m_ClientMsg = new ServerEventDispath();
m_ClientMsg.RegistEvent((int)NetMsgID.C2S_ASK_SEND_AUDIO_BEGIN, Action_C2S_ASK_SEND_AUDIO_BEGIN);
m_ClientMsg.RegistEvent((int)NetMsgID.C2S_ASK_SEND_AUDIO, Action_C2S_ASK_SEND_AUDIO);
m_ClientMsg.RegistEvent((int)NetMsgID.C2S_ASK_SEND_AUDIO_END, Action_C2S_ASK_SEND_AUDIO_END);
} // Update is called once per frame
void Update ()
{
if(!m_Destroy)
{
LanSocket.ClientMsgUnPack clientMsg = null;
m_GameNet.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; MonoBehaviour.print("Update EventID " + mNode.m_EventID + " ID: " + clientMsg.GetMsgID());
m_ClientMsg.AddEvent(mNode);
} if(!"".Equals(m_Reciver.GetIP()))
{
m_Sender.Send();
} m_ClientMsg.Proccess();
}
} void OnDestroy()
{
m_Destroy = true;
m_GameNet.Destroy();
m_Reciver.Destroy();
m_Sender.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();
m_GameNet.SendTo(ref sendMsg, msg.GetUserID());
} void Action_C2S_ASK_SEND_AUDIO_BEGIN(LanSocket.ClientMsgUnPack msg)
{
m_AudioOffset = ;
m_AudioLen = ;
} void Action_C2S_ASK_SEND_AUDIO(LanSocket.ClientMsgUnPack msg)
{
long userID = msg.GetUserID();
ushort dataLen = msg.ReadUShort();
byte[] audioData = msg.ReadByte(dataLen); // string result = string.Empty;
// for (int i = 0; i < dataLen; i++)
// {
// result += System.Convert.ToString(audioData[i], 16) + " ";
// }
// print(result); System.Buffer.BlockCopy(audioData, , m_AudioData, m_AudioOffset, (int)dataLen);
m_AudioOffset += dataLen;
} void Action_C2S_ASK_SEND_AUDIO_END(LanSocket.ClientMsgUnPack msg)
{
print("audio length: " + m_AudioOffset);
short[] decodeData = new short[m_AudioOffset / ];
for (int i = ; i < decodeData.Length; ++i)
{
decodeData[i] = System.BitConverter.ToInt16(m_AudioData, i * );
}
MicroPhoneInput.getInstance().PlayClipData(decodeData); // string result = string.Empty;
// for (int i = 0; i < m_AudioOffset; i++)
// {
// result += System.Convert.ToString(m_AudioData[i], 16) + " ";
// }
// print(result);
}
}
ServerMain.cs
以上为修改过的全部代码。
u3d局域网游戏网络(c# socket select 模型)——续的更多相关文章
- u3d局域网游戏网络(c# socket select 模型)
之前写了一篇. 发完之后第二天实际应用到游戏之后还是发现了一些小毛病. 比如网络模块有重复使用(多对象)的情况.所以将静态类该成了普通类. 比如安卓下会有些异常出现导致游戏逻辑不正常.所以网络相关的函 ...
- c# socket select 模型代码(u3d)
其实写过多次网络链接.但是因为换了工作,又没电脑在身边,所以以前的代码都没办法翻出来用. 所以从今天起,一些常用的代码只好放到网上. 公司有一个局域网的游戏.本来想用u3d的rpc就可以完成.但是后来 ...
- 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 ...
- socket之 select模型
前段时间一直想学习网络编程的select模型,看了<windows网络编程>的介绍,参考了别人的博客. 这里的资料主要来自http://www.cnblogs.com/RascallySn ...
- 网络编程第六讲Select模型
网络模型第六讲Select模型 一丶Select模型是什么 以前我们讲过一个迭代模型.就是只服务一个客户端连接.但是实际网络编程中.复杂的很多. 比如一个 C/S架构程序 (客户端/服务端) 客户端很 ...
- windows socket编程select模型使用
int select( int nfds, //忽略 fd_ser* readfds, //指向一个套接字集合,用来检测其可读性 ...
- socket编程的select模型
在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...
随机推荐
- 欢迎来怼--第七次Scrum会议
一.小组信息 队名:欢迎来怼 小组成员: 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/19 17:05~17:17,总计12min. 地 ...
- 软件工程课堂作业(二)续——升级完整版随机产生四则运算题目(C++)
一.设计思想: 1.根据题目新设要求,我将它们分为两类:一类是用户输入数目,根据这个数目改变一系列后续问题:另一类是用户输入0或1,分情况解决问题. 2.针对这两类要求,具体设计思路已在上篇博文中写出 ...
- oracle数据库之PL/SQL 块结构和组成元素
一.PL/SQL 块 (一)PL/SQL 程序由三个块组成,即声明部分.执行部分.异常处理部分 PL/SQL 块的结构如下: 1.DECLARE /* 声明部分: 在此声明 PL/SQL 用到的变量, ...
- Atom Editor 插件 atom-less 的使用方法
一.下载安装 atom-less atom-less 项目在这里:https://github.com/schmuli/atom-less 安装方法请参考这篇博文:http://blog.csdn.n ...
- 转:概率主题模型简介 --- ---David M. Blei所写的《Introduction to Probabilistic Topic Models》的译文
概率主题模型简介 Introduction to Probabilistic Topic Models 转:http://www.cnblogs.com/siegfang/archive/2 ...
- [洛谷P4781]【模板】拉格朗日插值
题目大意:给你$n(n\leqslant2000)$个点,要你求$n-1$次经过这$n$个点的多项式在$k$处的值 题解:$Lagrange$插值:$$f_x=\sum\limits_{i=1}^ky ...
- 【Codeforces Round #406 (Div. 2)】题解
The Monster 签到题,算一下b+=a和d+=c,然后卡一下次数就可以了. Not Afraid 只要一组出现一对相反数就是安全的. Berzerk 题意:[1,n],两个人轮流走,谁能走到1 ...
- MySQL安装出现“不是内部或外部命令,也不是可执行程序”等一系列问题的解决方案
MySQL安装出现“不是内部或外部命令,也不是可执行程序” 一.这是应该是环境变量处问题了,设置如下: 1)右击我的电脑选择“属性”,找到“高级系统设置” 2)在系统属性下,选择“高级”中的“环境变量 ...
- [Leetcode] Binary tree postorder traversal二叉树后序遍历
Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...
- BZOJ2588 Count on a tree 【树上主席树】
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Submit: 7577 Solved: 185 ...