为了准备毕业设计,学习了服务器与客户端之间传输的一些简单的知识,并跟着网络上的教程制作了一个简易的Unity聊天室
服务器:用C# .Net Framework写的
结构分为:main(主函数)、Server类(用于服务器的开启和接收客户端连接)、Client类(接收消息和发送消息)、Message类(用于消息的解析和包装)
main:
class Program { static void Main(string[] args) { string ip = "127.0.0.1";//这个ip地址表示本机 int port = 6688; //测试用的端口号,应该可以自己随便写吧 Server server = new Server(ip, port); server.Start(); Console.ReadKey(); } }
Server:
public class Server { private Socket serverSocket = null; private List<Client> clientList = new List<Client>(); private Socket clientSocket = null; public Server() { } public Server(string ip,int port) { //创建socket,然后绑定ip地址和端口号 //传输类型是流,使用的协议是Tcp serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); EndPoint point = new IPEndPoint(IPAddress.Parse(ip), port); serverSocket.Bind(point); } public void Start() { serverSocket.Listen(0); //开始监听 0表示等待连接队列的最大数 Console.WriteLine("开始监听"); Console.WriteLine("等待客户端连接"); serverSocket.BeginAccept(AcceptCallBack, null); //等待客户端连接,AcceptCallBack是回调,第三个参数目前还没用过,没去了解作用 TODO } private void AcceptCallBack(IAsyncResult ar) { clientSocket = serverSocket.EndAccept(ar); Console.WriteLine("一个客户端连接"); Client client = new Client(clientSocket,this); //当客户端连接上后,用Client类处理消息的接收与发送 clientList.Add(client); client.Start(); serverSocket.BeginAccept(AcceptCallBack, null); //服务器继续等待其他客户端连接 } public void Broadcast(string message) //广播消息 { foreach(Client client in clientList) { client.SendMessage(message); } } }
Client:
public class Client { private Socket clientSocket; private Server server; private Message msg = new Message(); public Client() { } public Client(Socket clientSocket,Server server) { this.clientSocket = clientSocket; this.server = server; } public void Start() { //判断客户端是否被关闭 if (clientSocket.Connected == false || clientSocket.Poll(10, SelectMode.SelectRead)) { clientSocket.Close(); return; } //等待从客户端的消息的接收 clientSocket.BeginReceive(msg.data, 0, msg.data.Length, SocketFlags.None, ReceiveCallBack, null); } private void ReceiveCallBack(IAsyncResult ar) { try { //需要用try catch 捕捉异常,不然出现异常服务器会终止 //判断客户端是否被关闭 if (clientSocket.Connected==false || clientSocket.Poll(10,SelectMode.SelectRead)) { clientSocket.Close(); return; } int len = clientSocket.EndReceive(ar);//返回的len表示接收的数据长度 if (len == 0)//客户端被关闭了 服务端会接收到0字节的消息 { clientSocket.Close(); return; } msg.Read(len, OnProessMassage);//Message类解析消息 //Console.WriteLine("receive:" + message); clientSocket.BeginReceive(msg.data, 0, msg.data.Length, SocketFlags.None, ReceiveCallBack, null); } catch (Exception e) { Console.WriteLine("ReceiveCallBack:" + e); } } private void OnProessMassage(string msg) { server.Broadcast(msg);//通过服务器广播消息 } public void SendMessage(string message) { //判断客户端是否被关闭 发送的时候客户端也可能被关闭 if (clientSocket.Connected == false || clientSocket.Poll(10, SelectMode.SelectRead)) { clientSocket.Close(); return; } //MethodInfo mi = msg.GetType().GetMethod("Pack"); clientSocket.Send(msg.Pack(message));//发送消息给客户端 //Console.WriteLine("send:"+message); } }
Message:
//这里只是简单的处理消息;解析:从byte[] ->string;发送:string->byte[]
class Message { public byte[] data = new byte[1024]; public void Read(int len,Action<string>OnProessMessage) { string message = Encoding.UTF8.GetString(data, 0, len); OnProessMessage(message); Array.Clear(data, 0, len); } public byte[] Pack(string msg) { byte[] dataBytes = Encoding.UTF8.GetBytes(msg); return dataBytes; } }