服务器下使用Socket_UDP协议怎么实现局域网内广播和接收
一开始接到这个项目需求时,其实挺懵逼的。因个人目前经验并不多,想过各种实现方案也利用TCP UDP 个人实验了不下10次,
总算再网上找到借鉴的同时开发出目前适合自己项目的一种方案。下面就来分享我的代码(如有不同意见还望指正):
using System;
using System.Text;
using System.Threading;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.Collections.Generic;
public class Glowworm : MonoBehaviour
{
private bool isFirstStart = false;
//广播
private Socket socket;
private IPEndPoint iep1;
private byte[] data = new byte[2048 * 3];
public int udpPort = 9090;
private float intervalTime = 2.0f;
private bool isIntervalSend = false;
private float curTime = 0;
//接收
private byte[] data_Receive = new byte[2048 * 3];
//private string Error_Message;
private Thread t_Reveive;
private EndPoint ep;
private bool IsStop = false;
private Socket UDPReceive;
//解析
private List<string> allCallBackMessList = new List<string>();
private string CallBackMessage;
private static SocketMsgData socketMsgData = null;
//事件管理
//保持socket消息与主线程同步
private ManualResetEvent allDone = new ManualResetEvent(false);
private static readonly object Lock = new object(); //s锁
//单例
private static Glowworm instance;
public static Glowworm Instance
{
get
{
return instance;
}
}
#region 事件函数
public void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
isFirstStart = true;
}
else
{
Destroy(gameObject);
return;
}
}
private void Start()
{
isFirstStart = true;
//广播
//BroadcastIP();
}
private void Update()
{
//if (Input.GetKeyDown(KeyCode.Q))
//{
// Send("3333333333333333333333333333");
//}
//类似心脏跳动检测 定时2秒一次(广播告知所有局域网内IP)
curTime += Time.fixedDeltaTime;
if (curTime >= intervalTime && isIntervalSend)
{
Send("0_0_0_0");
curTime = 0;
}
//信息处理
if (socketMsgData != null)
{
lock (Lock)
{
if(socketMsgData.MessageType == (int)MessageType.Register)
{
//如果是再创建则需要保证被管控
Server.curAcceptUserTravel = socketMsgData.TravelSceneObj;
Debug.Log(Server.curAcceptUserTravel);
}
CheckDataObjState(socketMsgData);
Debug.Log("Update");
}
socketMsgData = null;
allDone.Set();
}
}
#endregion
#region 自定义函数
//update 中检测信息对象函数
public void CheckDataObjState(SocketMsgData _socketMsgData)
{
Debug.Log(_socketMsgData.ToString());
//获取临时路径
//注意 这个也判断了是否需要接入数据库的路径
string tmpUrlPath = PathManager.Instance.GetSendToWebMssager(_socketMsgData);
if (string.IsNullOrEmpty(tmpUrlPath))
{
return;
}
else
{
//如果路径不为空则接入数据库
_socketMsgData.m_urlPath = WebSeverHandler.Instance.WebServerConfig + tmpUrlPath;
Debug.Log(_socketMsgData.m_urlPath);
//获取
StartCoroutine(WebSeverHandler.Request(_socketMsgData, CallBackEventFunction));
}
}
//事件回调函数
public void CallBackEventFunction(object _callBackMsg)
{
SocketMsgData dataObj = _callBackMsg as SocketMsgData;
Debug.Log(dataObj.callMessage);
switch ((MessageType)dataObj.MessageType)
{
case MessageType.Student:
{
if (!string.IsNullOrEmpty(dataObj.callMessage) && dataObj.callMessage.Length > 2)
{
dataObj.callMessage = "1";
Debug.Log(dataObj.callMessage);
}
else
{
dataObj.callMessage = "0";
Debug.Log(dataObj.callMessage);
}
break;
}
case MessageType.Teacher:
{
if (!string.IsNullOrEmpty(dataObj.callMessage) && dataObj.callMessage.Length > 2)
{
dataObj.callMessage = "1";
Debug.Log(dataObj.callMessage);
}
else
{
dataObj.callMessage = "0";
Debug.Log(dataObj.callMessage);
}
break;
}
case MessageType.CreateInfo:
{
break;
}
case MessageType.MoveInfo:
{
break;
}
case MessageType.DestroyInfo:
{
break;
}
case MessageType.AsynInfo:
{
break;
}
case MessageType.ResultCheck:
{
break;
}
case MessageType.TestPaperdownLoad:
{
break;
}
case MessageType.ScoreChange:
{
break;
}
default: break;
}
this.Send(dataObj.ToString());
//直接发送是否登录
//Send(_callBackMsg + "192.168.5.199_1");
Debug.Log(dataObj.callMessage);
}
#endregion
#region udp 广播和接收
//广播
public void BroadcastIP()
{
if(isFirstStart) //判断是否第一次打开
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
iep1 = new IPEndPoint(IPAddress.Broadcast, udpPort);
data = Encoding.UTF8.GetBytes("111");
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
isIntervalSend = true;//开始间隔广播
StartReceive(); //开始接收
isFirstStart = false;
}
else
{
IsStop = false; //继续间隔发送
isIntervalSend = true; //继续接收
StartReceive(); //开始接收
}
}
//广播发送
public void Send(string msg)
{
msg += "#";
Debug.Log(msg);
data = Encoding.UTF8.GetBytes(msg);
socket.SendTo(data, iep1);
}
//接收
private void StartReceive()
{
try
{
//UDPReceive = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
ep = new IPEndPoint(IPAddress.Any, udpPort);
//socket.Bind(ep);
data_Receive = new byte[2048*3];
t_Reveive = new Thread(Receive);
t_Reveive.IsBackground = true;
t_Reveive.Start();
}
catch (Exception e)
{
Debug.LogError("错误信息:" + e.Message);
}
}
//线程中执行函数
private void Receive()
{
while (!IsStop)
{
if (socket.Available <= 0) continue;
int recv = socket.ReceiveFrom(data_Receive, ref ep);
if(recv > 0)
{
string msg = Encoding.UTF8.GetString(data_Receive, 0, recv);
Debug.Log("接收消息:" + msg);
allCallBackMessList.Clear(); //清空
//解析包
AnalyzePackage(msg);
//分离出集合中信息对象并进行数据处理
foreach (string mess in allCallBackMessList)
{
string[] tmpArray = mess.Split('_');
//string.IsNullOrEmpty(tmpArray[1]) && string.IsNullOrEmpty(tmpArray[2]
if (tmpArray.Length < 1)
{
continue;
}
else
{
// 消息处理
allDone.Reset(); //事件管控 保证下列事件只有一个线程在使用(避免争抢)
socketMsgData = new SocketMsgData();
socketMsgData.InitData();
socketMsgData.SetMessage2Obj(mess);
Debug.Log(socketMsgData.ToString());
//SplitMsgType(socketMsgData); //初步分割
allDone.WaitOne(); //等待主线程执行
}
//把收到的数据再次发送给原始目标
//Send(mess);
Debug.Log(mess);
}
}
}
}
//old 初步信息分割
public void SplitMsgType(SocketMsgData _msgData)
{
if (_msgData == null) return;
switch ((MessageType)_msgData.MessageType)
{
case MessageType.Student:
case MessageType.Teacher:
case MessageType.ResultCheck:
case MessageType.TestPaperdownLoad:
case MessageType.ScoreChange:
case MessageType.CreateInfo:
case MessageType.MoveInfo:
case MessageType.DestroyInfo:
case MessageType.AsynInfo:
default: break;
}
}
//暂停接收
public void StopReceive()
{
IsStop = true;
t_Reveive.Abort();
isIntervalSend = false;
}
//解析包的函数
void AnalyzePackage(string message)
{
CallBackMessage += message;
//Debug.Log(CallBackMessage.ToString());
//#作为一条消息的结尾
int index = -1;
while ((index = CallBackMessage.IndexOf("#")) != -1)
{
allCallBackMessList.Add(CallBackMessage.Substring(0, index));
//Debug.Log(CallBackMessage.Substring(0, index));
CallBackMessage = CallBackMessage.Substring(index + 1);
}
}
//程序推出时执行
private void OnApplicationQuit()
{
//接收
IsStop = true;
//广播
isIntervalSend = false;
if(socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
//t_Reveive.Abort();
}
#endregion
}
本篇文章属于个人笔记,有不同意见的,还望指正,希望自己能更好的再编程路上走下去。