一、逻辑思路
创建套接字Socket 用于连接服务端 和判断是否连接客户端的开关
Socket socket
private bool isConnected = false
2、首先创建两个队列去临时存储接收和发送的消息
public Queue<string> sendMsgQueue = new Queue<string>();
public Queue<string> receiveQueue = new Queue<string>();
3、再创建接收消息的字节数组
byte[] receiveBytes = new byte[1024*1024];
int receiveNum;
连接服务器的方法功能模块Connect(string host,int port) 传入服务端的IP和端口号
判断是否连接 if (isConnected) return; 如果没有连接 就跳出连接
设置Socket的连接方式 流程和服务端的差不多
socket=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(host), port);
使用Try{}Catch(){} 去捕捉可能出现的问题
Try中 放的是连接成功的代码逻辑
socket.Connect(ipPoint);
ThreadPool.QueueUserWorkItem(SendMsg);
ThreadPool.QueueUserWorkItem(receiveMsg);
异步发送消息的方法 需要循环判断是否发送消息 所以要用到While
SendMsg(object obj)
使用While(!isConnected)去控制收发消息 去判断队列是否不为空sendMsgQueue.Count > 0
如果不为空的话 就取出队列的首个元素进行发送到客户端 socket.Send(Encoding.UTF8.GetBytes(sendMsgQueue.Dequeue()));
其中,存在一个问题,怎么把信息存到队列中去呢?
再创建一个外部方法Send(string info) 进行将需要发送的消息存放队列中去
方法体内部只要将info存放到队列中 sendMsgQueue.Enqueue(info);
SendMsg不停地循环判断队列是否为空,不为空就取出,进行发送消息 实现了客户端发送消息的逻辑。
异步接收消息的方法 需要循环判断是否收到消息 所以要用到While
receiveMsg(object obj)
使用While(!isConnected)去控制接收消息
判断是否收到消息if (socket.Available > 0)
收到的话
receiveNum = socket.Receive(receiveBytes);
receiveQueue.Enqueue(Encoding.UTF8.GetString(receiveBytes,0,receiveNum));
存到队列了之后 怎么才能打印出来呢?
放到Update中进行判断队列是否大于0大于0的话就取出元素
if (receiveQueue.Count > 0)
{
print(receiveQueue.Dequeue());
}
关闭方法
public void Close()
{
if(socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
isConnected = false;
}
}
private void OnDestroy()
{
Close();
}
代码
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
public class NetMgr : MonoBehaviour
{
//单例模式
public static NetMgr instance;
public static NetMgr Instance=>instance;
private bool isConnected = false; //是否连接到服务器的开关
//创建一个队列 用来存储要发送的消息
public Queue<string> sendMsgQueue = new Queue<string>();
//创建一个队列 用来存储要接收的消息
public Queue<string> receiveQueue = new Queue<string>();
//接收消息的容器
byte[] receiveBytes = new byte[1024*1024];
int receiveNum;
Socket socket;
private void Awake()
{
instance = this;
}
private void Update()
{
if (receiveQueue.Count > 0)
{
print(receiveQueue.Dequeue());
}
}
//连接服务器 传入IP和端口号
public void Connect(string host, int port)
{
//1.判断是否是连接状态 如果是 就返回
if (isConnected)
return;
//设置连接方式
socket=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获取服务器的 IPEndPoint
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(host), port); //里面输入服务器的IP和端口号
try
{
socket.Connect(ipPoint); //连接 成功
Send("连接成功");
//进行收发消息
//用线程池进行嗲用
ThreadPool.QueueUserWorkItem(SendMsg);
ThreadPool.QueueUserWorkItem(receiveMsg);
}
catch(SocketException e)
{
if (e.ErrorCode == 10061)
{
print("服务器拒绝连接");
}
else
{
print("连接服务器失败" + e.ErrorCode);
}
return;
}
}
/// <summary>
/// 发送消息 外部
/// </summary>
/// <param name="info"></param>
public void Send(string info)
{
sendMsgQueue.Enqueue(info);
}
public void SendMsg(object obj)
{
while (!isConnected)
{
if(sendMsgQueue.Count > 0)
{
socket.Send(Encoding.UTF8.GetBytes(sendMsgQueue.Dequeue()));
}
}
}
/// <summary>
/// 不停的接收消息
/// </summary>
private void receiveMsg(object obj)
{
while (!isConnected)
{
if (socket.Available > 0)
{
//获取长度
receiveNum = socket.Receive(receiveBytes);
//解析
receiveQueue.Enqueue(Encoding.UTF8.GetString(receiveBytes,0,receiveNum));
}
}
}
public void Close()
{
if(socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
//关闭接收和发送服务
isConnected = false;
}
}
private void OnDestroy()
{
Close();
}
}