实现客户端的网络不影响主线程且随时与服务器通信
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
//网络管理器(单例模式)
public class NetMgr : MonoBehaviour
{
private static NetMgr instance;
//用于发送消息的队列 公共容器 主线程往里边放 发送线程从里边取
private Queue<string> sendMgsQueue = new Queue<string>();
//用于接收消息的队列 公共容器 存放线程往里放 主线程从里边取
private Queue<string> receiveMgsQueue = new Queue<string>();
public static NetMgr Instance => instance;
//用于收消息的水桶(容器)
private byte[] bytes = new byte[1024 * 1024];
//用于返回字节数组大小
private int receiveNum;
//客户端Socket
public Socket socket;
private bool IsConnect=false;
void Awake()
{
instance = this;
}
void Update()
{
if(receiveMgsQueue .Count >0)
{
print(receiveMgsQueue.Dequeue());
}
}
//连接服务器
public void Connect(string ip,int port)
{//如果是非链接状态,直接返回
if (IsConnect )
return;
if(socket==null)
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//连接服务端
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip),port);
try
{
socket.Connect(ipPoint);
IsConnect = true;
//使用线程池节约性能
ThreadPool.QueueUserWorkItem(SendMsg);
ThreadPool.QueueUserWorkItem(ReceiveMsg);
}
catch (SocketException e)
{
if (e.ErrorCode == 10061)
print("服务器拒绝连接");
else
print("连接失败" + e.ErrorCode + e.Message);
}
}
//发送消息
public void Send(string info)
{
sendMgsQueue.Enqueue(info);
}
public void SendMsg(object obj)
{
if(sendMgsQueue .Count >0)
{
socket.Send(Encoding.UTF8.GetBytes(sendMgsQueue.Dequeue()));
}
}
//不停的接收消息
public void ReceiveMsg(object obj)
{
while (IsConnect)
{
if (socket.Available > 0)
{
receiveNum = socket.Receive(bytes);
//解析字符数组成字符串,放入公共容器中
receiveMgsQueue.Enqueue(Encoding.UTF8.GetString(bytes, 0, receiveNum));
}
}
}
public void Close()
{
if(socket !=null)
{
IsConnect = false;
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
private void OnDestroy()
{
Close();
}
}
主函数入口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
if(NetMgr .Instance ==null)
{
GameObject obj = new GameObject("Net");
obj.AddComponent<NetMgr>();
}
NetMgr.Instance.Connect("127.0.0.1", 8080);
}
// Update is called once per frame
void Update()
{
}
}
客户端向服务器发消息
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Lesson7 : MonoBehaviour
{
public Button btu;
public InputField input;
void Start()
{
btu.onClick.AddListener(() =>
{
if (input.text != "")
{
NetMgr.Instance.Send(input.text);
}
}
);
}
// Update is called once per frame
void Update()
{
}
}