30.网络通信-套接字Socket-TCP通信-异步-客户端
30.1 知识点
创建TcpNetAsyncManager,实现Monobehaviour的单例。定义和服务器进行连接的Socket还有缓存字节数组及长度
// 用于和服务器进行连接的Socket
private Socket socket;
// 用于处理分包时缓存的字节数组和字节数组长度
private byte[] cacheBytes = new byte[1024 * 1024];
private int cacheNum = 0;
实现连接服务器和关闭连接的方法
// 连接服务器
public void Connect(string ip, int port)
{
// 检查当前是否已经连接,如果已经连接则直接返回
if (socket != null && socket.Connected)
return;
// 创建IP地址和端口信息
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
// 创建一个Socket用于TCP连接
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建异步Socket事件参数
SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
socketAsyncEventArgs.RemoteEndPoint = ipPoint;
// 注册连接完成时的回调函数
socketAsyncEventArgs.Completed += (socket, socketAsyncEventArgs) =>
{
if (socketAsyncEventArgs.SocketError == SocketError.Success)
{
print("连接成功");
// 设置接收消息的Socket事件参数
SocketAsyncEventArgs receiveSocketAsyncEventArgs = new SocketAsyncEventArgs();
receiveSocketAsyncEventArgs.SetBuffer(cacheBytes, 0, cacheBytes.Length);
receiveSocketAsyncEventArgs.Completed += ReceiveCallBack;
this.socket.ReceiveAsync(receiveSocketAsyncEventArgs);
}
else
{
print("连接失败" + socketAsyncEventArgs.SocketError);
}
};
// 开始异步连接
socket.ConnectAsync(socketAsyncEventArgs);
}
// 关闭连接
public void Close()
{
if (socket != null)
{
// 关闭连接前先关闭读写流
socket.Shutdown(SocketShutdown.Both);
// 断开连接
socket.Disconnect(false);
// 关闭Socket
socket.Close();
socket = null;
}
}
实现客户端收消息回调函数和发消息给服务端函数
// 客户端收消息完成的回调函数
private void ReceiveCallBack(object obj, SocketAsyncEventArgs receiveSocketAsyncEventArgs)
{
if (receiveSocketAsyncEventArgs.SocketError == SocketError.Success)
{
// 解析消息,目前使用UTF-8编码将字节数组转换为字符串
print(Encoding.UTF8.GetString(receiveSocketAsyncEventArgs.Buffer, 0, receiveSocketAsyncEventArgs.BytesTransferred));
// 继续接收消息,重置接收缓冲区
receiveSocketAsyncEventArgs.SetBuffer(0, receiveSocketAsyncEventArgs.Buffer.Length);
// 继续异步接收消息
if (this.socket != null && this.socket.Connected)
socket.ReceiveAsync(receiveSocketAsyncEventArgs);
else
Close();
}
else
{
print("接受消息出错" + receiveSocketAsyncEventArgs.SocketError);
// 关闭客户端连接
Close();
}
}
// 发送消息给服务端
public void Send(string str)
{
if (this.socket != null && this.socket.Connected)
{
// 将字符串转换为字节数组
byte[] bytes = Encoding.UTF8.GetBytes(str);
// 创建异步Socket事件参数用于发送消息
SocketAsyncEventArgs sendSocketAsyncEventArgs = new SocketAsyncEventArgs();
sendSocketAsyncEventArgs.SetBuffer(bytes, 0, bytes.Length);
sendSocketAsyncEventArgs.Completed += (socket, args) =>
{
if (args.SocketError != SocketError.Success)
{
print("发送消息失败" + args.SocketError);
Close();
}
};
// 开始异步发送消息
this.socket.SendAsync(sendSocketAsyncEventArgs);
}
else
{
// 如果Socket未连接,则关闭连接
Close();
}
}
在客户端入口添加测试代码,开启服务端和客户端进行收发消息的测试
public InputField InputField;
public Button sendButton;
void Start()
{
TcpNetAsyncManager.Instance.Connect("127.0.0.1", 8080);
//直接发消息测试
sendButton.onClick.AddListener(() =>
{
if (InputField.text != "")
TcpNetAsyncManager.Instance.Send(InputField.text);
});
}
30.2 知识点代码
TcpNetAsyncManager
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
public class TcpNetAsyncManager : BaseSingletonInMonoBehaviour<TcpNetAsyncManager>
{
// 用于和服务器进行连接的Socket
private Socket socket;
// 用于处理分包时缓存的字节数组和字节数组长度
private byte[] cacheBytes = new byte[1024 * 1024];
private int cacheNum = 0;
// 连接服务器
public void Connect(string ip, int port)
{
// 检查当前是否已经连接,如果已经连接则直接返回
if (socket != null && socket.Connected)
return;
// 创建IP地址和端口信息
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port);
// 创建一个Socket用于TCP连接
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建异步Socket事件参数
SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
socketAsyncEventArgs.RemoteEndPoint = ipPoint;
// 注册连接完成时的回调函数
socketAsyncEventArgs.Completed += (socket, socketAsyncEventArgs) =>
{
if (socketAsyncEventArgs.SocketError == SocketError.Success)
{
print("连接成功");
// 设置接收消息的Socket事件参数
SocketAsyncEventArgs receiveSocketAsyncEventArgs = new SocketAsyncEventArgs();
receiveSocketAsyncEventArgs.SetBuffer(cacheBytes, 0, cacheBytes.Length);
receiveSocketAsyncEventArgs.Completed += ReceiveCallBack;
this.socket.ReceiveAsync(receiveSocketAsyncEventArgs);
}
else
{
print("连接失败" + socketAsyncEventArgs.SocketError);
}
};
// 开始异步连接
socket.ConnectAsync(socketAsyncEventArgs);
}
// 关闭连接
public void Close()
{
if (socket != null)
{
// 关闭连接前先关闭读写流
socket.Shutdown(SocketShutdown.Both);
// 断开连接
socket.Disconnect(false);
// 关闭Socket
socket.Close();
socket = null;
}
}
// 客户端收消息完成的回调函数
private void ReceiveCallBack(object obj, SocketAsyncEventArgs receiveSocketAsyncEventArgs)
{
if (receiveSocketAsyncEventArgs.SocketError == SocketError.Success)
{
// 解析消息,目前使用UTF-8编码将字节数组转换为字符串
print(Encoding.UTF8.GetString(receiveSocketAsyncEventArgs.Buffer, 0, receiveSocketAsyncEventArgs.BytesTransferred));
// 继续接收消息,重置接收缓冲区
receiveSocketAsyncEventArgs.SetBuffer(0, receiveSocketAsyncEventArgs.Buffer.Length);
// 继续异步接收消息
if (this.socket != null && this.socket.Connected)
socket.ReceiveAsync(receiveSocketAsyncEventArgs);
else
Close();
}
else
{
print("接受消息出错" + receiveSocketAsyncEventArgs.SocketError);
// 关闭客户端连接
Close();
}
}
// 发送消息给服务端
public void Send(string str)
{
if (this.socket != null && this.socket.Connected)
{
// 将字符串转换为字节数组
byte[] bytes = Encoding.UTF8.GetBytes(str);
// 创建异步Socket事件参数用于发送消息
SocketAsyncEventArgs sendSocketAsyncEventArgs = new SocketAsyncEventArgs();
sendSocketAsyncEventArgs.SetBuffer(bytes, 0, bytes.Length);
sendSocketAsyncEventArgs.Completed += (socket, args) =>
{
if (args.SocketError != SocketError.Success)
{
print("发送消息失败" + args.SocketError);
Close();
}
};
// 开始异步发送消息
this.socket.SendAsync(sendSocketAsyncEventArgs);
}
else
{
// 如果Socket未连接,则关闭连接
Close();
}
}
}
Lesson30_网络通信_套接字Socket_TCP通信_异步_客户端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Lesson30_网络通信_套接字Socket_TCP通信_异步_客户端 : MonoBehaviour
{
public InputField InputField;
public Button sendButton;
void Start()
{
TcpNetAsyncManager.Instance.Connect("127.0.0.1", 8080);
//直接发消息测试
sendButton.onClick.AddListener(() =>
{
if (InputField.text != "")
TcpNetAsyncManager.Instance.Send(InputField.text);
});
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com