开发Unity项目过程中,即时通信功能来完成服务器与客户端自定义的数据结构封装。
如果要序列化和数据封装参考:Unity3D之C#用Socket传数据包
蓝鸥3G封装的类
客户端脚本ClientScript
/// <summary> /// Client Script. /// Created By 蓝鸥3G 2014.08.23 /// </summary> using UnityEngine; using System.Collections; public class ClientScript: MonoBehaviour { string msg = ""; // Use this for initialization LOSocket client; void Start () { client = LOSocket.GetSocket(LOSocket.LOSocketType.CLIENT); client.InitClient ("127.0.0.1", 2222, ((string content) => { //收到服务器的回馈信息 })); } void OnGUI() { msg = GUI.TextField(new Rect(0, 0, 500, 40), msg); if(GUI.Button(new Rect(0, 50, 100, 30), "Send")) { client.SendMessage (msg); } } }
服务器端脚本
using UnityEngine; using System.Collections; public class ServerScript : MonoBehaviour { private string receive_str; LOSocket server; // Use this for initialization void Start () { server = LOSocket.GetSocket(LOSocket.LOSocketType.SERVER); //初始化服务器 server.InitServer((string content) => { receive_str = content; }); } void OnGUI() { if (receive_str != null) { GUILayout.Label (receive_str); } } }
LOSocket框架
using UnityEngine; using System.Collections; using System.Net; using System.Net.Sockets; using System.Text; //收到消息后的委托回调 public delegate void ReceiveCallBack(string content); public class LOSocket{ //可以创建的Socket端口类型 public enum LOSocketType { CLIENT = 0, SERVER = 1, } #region --------取消构造器 private LOSocket() { } #endregion #region --------公共代码 //通过静态方法获取不同的端口类型 public static LOSocket GetSocket(LOSocket.LOSocketType type) { LOSocket socket = null; switch (type) { case LOSocketType.CLIENT: { //创建一个新的客户端 socket = new LOSocket (); break; } case LOSocketType.SERVER: { //获取服务端 socket = GetServer (); break; } } return socket; } #endregion #region --------客户端部分代码 private Socket clientSocket; //声明客户端收到服务端返回消息后的回调委托函数 private ReceiveCallBack clientReceiveCallBack; //用来存储服务端返回的消息数据 byte[] Buffer = new byte[1024]; //初始化客户端Socket信息 public void InitClient(string ip,int port,ReceiveCallBack ccb) { this.clientReceiveCallBack = ccb; this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress address = IPAddress.Parse (ip); IPEndPoint ep = new IPEndPoint (address, port); this.clientSocket.Connect(ep); //开始异步等待接收服务端消息 this.clientSocket.BeginReceive (Buffer, 0, Buffer.Length, SocketFlags.None, new System.AsyncCallback(ReceiveFromServer), this.clientSocket); } //收到服务端返回消息后的回调函数 void ReceiveFromServer(System.IAsyncResult ar) { //获取当前正在工作的Socket对象 Socket worker = ar.AsyncState as Socket; int ByteRead=0; try { //接收完毕消息后的字节数 ByteRead = worker.EndReceive(ar); } catch (System.Exception ex) { this.clientReceiveCallBack (ex.ToString ()); } if (ByteRead > 0) { string Content = Encoding.Default.GetString (Buffer); //通过回调函数将消息返回给调用者 this.clientReceiveCallBack (Content); } //继续异步等待接受服务器的返回消息 worker.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new System.AsyncCallback(ReceiveFromServer), worker); } //客户端主动发送消息 public void SendMessage(string message) { if (message == null) return; message += "\r\n"; byte[] sendData = Encoding.UTF8.GetBytes (message); //异步发送消息请求 clientSocket.BeginSend (sendData, 0, sendData.Length, SocketFlags.None, new System.AsyncCallback (SendToServer), clientSocket); } //发送消息结束的回调函数 void SendToServer(System.IAsyncResult ar) { Socket worker = ar.AsyncState as Socket; worker.EndSend (ar); } #endregion #region -------服务器部分代码 //服务器端收到消息的存储空间 byte[] ReceiveBuffer = new byte[1024]; //服务器收到消息后的回调委托 private ReceiveCallBack callback; //单例模式 private static LOSocket serverSocket; private static LOSocket GetServer() { if (serverSocket == null) { serverSocket = new LOSocket(); } return serverSocket; } //初始化服务器信息 public void InitServer(ReceiveCallBack cb) { this.callback = cb; // 1. Socket server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 2. IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 2222); // 3. server_socket.Bind(endPoint); // 4. server_socket.Listen(10); // 5.开始异步等待客户端的请求链接 server_socket.BeginAccept (new System.AsyncCallback (Accept), server_socket); this.callback ("开启服务器" + endPoint.ToString()); } //接受到客户端的链接请求后的回调函数 void Accept(System.IAsyncResult ar){ //获取正在工作的Socket对象 Socket socket = ar.AsyncState as Socket; //存储异步操作的信息,以及用户自定义的数据 Socket worker = socket.EndAccept(ar); SocketError error; //开始异步接收客户端发送消息内容 worker.BeginReceive (ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new System.AsyncCallback (Receive), worker); //继续异步等待新的客户端链接请求 socket.BeginAccept(new System.AsyncCallback(Accept), socket); } //服务端收到客户端的消息后的回调函数 void Receive(System.IAsyncResult ar) { //获取正在工作的Socket对象 Socket worker = ar.AsyncState as Socket; int ByteRead=0; try { ByteRead = worker.EndReceive(ar); } catch (System.Exception ex) { this.callback (ex.ToString ()); } if (ByteRead > 0) { string Content = Encoding.Default.GetString (ReceiveBuffer); this.callback (Content); } //继续异步等待客户端的发送消息请求 worker.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new System.AsyncCallback(Receive), worker); } #endregion }
#python客户端测试代码
#! /usr/env/bin python #codinf=utf-8 import socket import time def Client(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('', 8000))#链接服务器 while 1: print 'enter something:', ent = raw_input() if ent == '': break sock.send(ent)#发送数据给服务器 time.sleep(1) data = sock.recv(1024)#接收服务器发过来到数据 print 'echo=>',data sock.close() if __name__ == '__main__': Client()
python服务器端测试代码
#! /usr/env/bin python #coding=utf-8 import socket #Server def Server(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 8000)) sock.listen(5)#监听,最大链接数 while 1: connection, address = sock.accept()#开始接受请求,进入等待阻塞状态,直到有链接到达 while 1: data = connection.recv(1024)#接收客户端发过来的数据 if not data: break print data,address connection.send(data)#发送数据到客户端,即上面到connection connection.close() if __name__ == '__main__': Server()
注意,这里没有对服务器的连接关闭,自己可以加上:sock.close()