本篇讲解的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