北京又在打雷下大雨了,学习Unity以来,越来越感兴趣,情不自禁的想要学习更多知识
这次自己搭建一个Socket模块,比较基础,适合新手学习,详细介绍Socket的搭建过程,同样会把详细过程在代码里进行注释~
在搭建Socket过程中,需要创建以下几个常用的方法:
1.创建套接字(socket)
2.绑定Ip和端口
3.监听方法
4.接收客户端请求的方法
5.收发消息的方法
创建SocketManger管理类
把客户端与服务端代码都写在新建的SocketManger里,并把SocketManger写成单例,方便调用
using System.Net; //引入套接字协议类 using System.Net.Sockets; using System; using System.Text; public class SocketManager { #region 单例类 private static SocketManager instance; private SocketManager() { } public static SocketManager Instance { get { if (instance == null) { instance = new SocketManager(); } return instance; } } #endregion public delegate void MyCallBack(string msg); //声明一个委托类型,在服务器和客户端工作的时候,会使用这个回调方法反馈当前交互的具体情况
服务端代码
#region 服务器代码 /* 创建服务器 * 等待客户端的连接 * 接受消息 */ Socket serverSocket; //创建服务器的套接字对象 MyCallBack serverCallBack; //定义一个服务器使用的回调委托对象 byte[] serverBuffer; //数据缓存区 文字,音频,视频,图片... public void InitServer(MyCallBack callBack) { serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //参数(1.使用IP地址的类型 2.套接字类型,使用TCP的流式传输 3.使用TCP协议) serverBuffer = new byte[1024]; //初始化缓冲区的大小 serverCallBack = callBack; //绑定初始化服务器的回调方法 IPEndPoint point = new IPEndPoint(IPAddress.Any, 34567); //参数(1.地址,代表一台电脑, 2.端口号表示一个应用) serverSocket.Bind(point); //绑定地址节点 serverSocket.Listen(10); //开始监听, 一旦监听成功,服务器就启动,10代表最大监听数量 serverCallBack("服务器启动成功"); //服务器开始进入等待用户连接的状态 //开辟一条子线程实时监测是否有人连接 //一旦有客户端连接,立马通知主线程,通知内容会以IAsyncResult 返回,连接者的所有信息 serverSocket.BeginAccept(ServerAccept, serverSocket); } //服务器开始接收的方法 void ServerAccept(IAsyncResult ar) { serverSocket = ar.AsyncState as Socket; //拿到当前连接服务器的Socket 对象 Socket workingSocket = serverSocket.EndAccept(ar); //将当前的Socket的全部信息交给一个新的Socket处理 workingSocket.BeginReceive(serverBuffer, 0, serverBuffer.Length, SocketFlags.None,ServerReceive, workingSocket); //(数据收发缓存区,起始位置,长度,不分类型,全部接收, 接受消息之后的回调,当前Socket的状态) serverSocket.BeginAccept(ServerAccept, serverSocket); //尾递归 } //服务器接收消息之后的回调方法 void ServerReceive(IAsyncResult ar) { Socket workingSorket = ar.AsyncState as Socket; int size=workingSorket.EndReceive(ar); //拿到接收到的数据一共有多少字节 string str = Encoding.UTF8.GetString(serverBuffer); //将接收到的byte数组转换成字符串 serverCallBack("接收到了" + size + "字节"); serverCallBack(str); workingSorket.BeginReceive(serverBuffer, 0, serverBuffer.Length, SocketFlags.None, ServerReceive, workingSorket); //尾递归 } #endregion
客户端代码
#region Socket clientSocket; MyCallBack clientCallBack; byte[] clientBuffer; //客户端连接服务器的方法 public void ClientConnectServer(string ip,int port,MyCallBack callBack) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientBuffer = new byte[1024]; clientCallBack = callBack; clientSocket.Connect(IPAddress.Parse(ip),port); //连接服务器 clientCallBack("连接服务器成功"); clientSocket.BeginReceive(clientBuffer, 0, clientBuffer.Length, SocketFlags.None,ClientReceive, clientSocket); } void ClientReceive(IAsyncResult ar) { Socket WorkingSocket = ar.AsyncState as Socket; int size=WorkingSocket.EndReceive(ar); //接收多少字节 string msg= Encoding.UTF8.GetString(clientBuffer); clientCallBack("接收了"+size+"字节"); clientCallBack(msg); clientSocket.BeginReceive(clientBuffer, size, clientBuffer.Length, SocketFlags.None, ClientReceive, WorkingSocket); } //客户端发送消息的方法 public void ClientSendMsg(string msg) { byte[] buffer= Encoding.UTF8.GetBytes(msg); clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallBack, clientSocket); } void SendCallBack(IAsyncResult ar) { Socket workingSocket = ar.AsyncState as Socket; workingSocket.EndSend(ar); clientCallBack("发送完成"); } #endregion
简单的Socket搭建完成,但是有一点小Bug,服务器进入等待用户连接状态后,会开辟子线程实时检测,没有关闭这条线程,因此在搭建服务器的脚本,可以在Start方法里写一个方法,在程序退出时关闭这条线程! 这个方法在关闭程序时自动调用
private void OnApplicationQuit() { serverSocket.Shutdown(SocketShutdown.Both); serverSocket.Close(); }
简单的Socket搭建完了,当然这只是非常基础的Socket传递,在实际使用中,还要考虑很多问题,比如Socket的沾包, 闭包,需要进一步处理