本篇讲解的socket虽然是基础,但是socket应用的思路体现了
还有某些服务器是 单线程 事件驱动 非阻塞I/O 的,这个图我就不化了,IO抛给底层的操作系统来做
服务器一般用一个字典来管理其服务的所有客户端,这个字典的key值可以是一个唯一的账号,也可以是本篇文章的客户端的IP地址,还有可能是接收到的客户端的socket
大并发通常的框架如下:
java的Mina,Netty框架
c++ Windows操作系统的的完成端口模型
c#的 Windows操作系统的SAEA模型
下面是一个专门用于封装一个客户端的数据封装类
class ChatClient { public static Hashtable ALLClients = new Hashtable(); // 客户列表 private TcpClient _client; // 客户端实体 public string _clientIP; // 客户端IP private string _clientNick; // 客户端昵称 private byte[] data; // 消息数据 private bool ReceiveNick = true; public ChatClient(TcpClient client) { this._client = client; this._clientIP = client.Client.RemoteEndPoint.ToString(); // 把当前客户端实例添加到客户列表当中 ALLClients.Add(this._clientIP, this); data = new byte[this._client.ReceiveBufferSize]; // 从服务端获取消息 client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null); //这个就是在做异步处理 } // 从客戶端获取消息 public void ReceiveMessage(IAsyncResult ar) { int bytesRead; try { // lock (this._client.GetStream()) // { bytesRead = this._client.GetStream().EndRead(ar); Console.Write("bytesRead"+bytesRead); // } Console.Write(bytesRead); if (bytesRead < 1) { ALLClients.Remove(this._clientIP); Broadcast(this._clientNick + "has left the chat"); //Broadcast这个函数是向所有的客户端广播消息 return; } else { string messageReceived = System.Text.Encoding.UTF8.GetString(data, 0, bytesRead); if (ReceiveNick) { this._clientNick = messageReceived; Broadcast(this._clientNick + " has joined the chat. huan yin ni");//Broadcast这个函数是向所有的客户端广播消息 //this.sendMessage("hello"); ReceiveNick = false; } else { Broadcast(this._clientNick + ">" + messageReceived); } } lock (this._client.GetStream()) { this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null); } } catch (Exception ex) { ALLClients.Remove(this._clientIP); Broadcast(this._clientNick + " has left the chat."); } } // 向客戶端发送消息 public void sendMessage(string message) { try { System.Net.Sockets.NetworkStream ns; lock (this._client.GetStream()) { ns = this._client.GetStream(); } // 对信息进行编码 byte[] bytesToSend = System.Text.Encoding.ASCII.GetBytes(message); ns.Write(bytesToSend, 0, bytesToSend.Length); ns.Flush(); } catch (Exception ex) { } } // 向客户端广播消息 public void Broadcast(string message) { Console.WriteLine(message); foreach (DictionaryEntry c in ALLClients) { ((ChatClient)(c.Value)).sendMessage(message + Environment.NewLine); } } }
FR:海涛高软(Hunk Xu) QQ技术交流群:386476712