服务器端的高性能实现(二)——windows下的第一步实现

既然是windows平台下的开发,就简单随个潮流,用VS2005好了,语言是c#。(其实是因为我熟悉这个,嘿嘿)

先开始搭建基本的框架吧。现在也没有太多的设计思路,就先一步一步开始吧,也算是个经验的积累。

首先创建一个类库的项目,叫什么呢?好的开始可是成功的一半啊,名字问题足足花了我5分钟的时间——汗。最后起了个很俗的名字:Server4Win。顾名思义,就是windows平台下的server。

好了,开始了。

先添加一个类,起名Core(好像也很俗哦)。然后就是给里面加东西了。

不过,写之前还是要先思考思考的。第一个问题就是这个类Core是干什么用的。干什么用呢?我给它安排的任务是对外提供server端的各种功能。而且考虑到一般server就一个,于是设计为单件模式。部分代码如下:

private static Core _core;

private Core()
{}

public static Core GetInstance
{
get
{if (_core == null)
_core = new Core();
return _core;}
}

好了,现在单件的框架已经搭好了,下面就是其他功能的添加了。当然了,我还是本着先实现,再优化的思路,所以刚开始的实现可能问题很多。之所以这么做,就是为了体会一下从无到有的过程,直接把现成的好东西拿来就用,我的消化能力可没那么好。

下面是我要给它添加两个功能,start和stop。

start就是启动服务。服务启动之后,客户端就可以与服务器建立连接了。stop当然就是停止服务了。

先说start吧。start里面具体干什么呢?简单来说,就是建立一个监听,等待客户端的连接,一旦发现有连接请求,就创建一个socket接受这个连接请求,然后继续监听。

start的第一次实现:
private TcpListener listener;
private string hostName = "192.168.14.13";//这个是我电脑的IP
private int portNumber = 9527;//9527??嘿嘿,很有趣的端口吧
private ArrayList allsockets = new ArrayList();//用于保存客户端的连接
public void Start()
{
if (listener == null)
{
listener = new TcpListener(IPAddress.Parse(hostName),portNumber);
}
listener.Start();
while(true)
{
TcpClient client = listener.AcceptTcpClient();
if (client != null)
allsockets.Add(client);
}
}

上面就是第一版的实现,就美名为V0.1吧。但是这个0.1里面问题很多。
首先,当系统调用AcceptTcpClient时会挂起,这会导致主线程失去响应,使服务器端永远的“不作为”,想停都停不了。也就是说,如果没有客户端来“激活”一下话,我们就完蛋了!
于是,在这个背景下,V0.2横空出世了。
重复的代码我就不写了。
public void Start()
{
if (listener == null)
{
listener = new TcpListener(IPAddress.Parse(hostName),portNumber);
}
listener.Start();
new Thread(new ThreadStart(ListenOnAccept)).Start();
}
private void ListenOnAccept()
{
while(true)
{
TcpClient client = listener.AcceptTcpClient();
if (client != null)
allsockets.Add(client);
}
}

这回看起来就好了很多。在0.2,我们解决了主线程挂起的问题。可是,还有一个没有解决。这个问题就是服务器端无法停止。因为只要一调用AcceptTcpClient,人家服务器就不理咱们了。为了解决这个问题,于是又出现了V0.3。同时,为了保证在start之后,不会再又被start了,我还要给core添加一个start的标示。
private bool _start = false;//start标示。
public void Start()
{
if (!_start)
{
if (listener == null)
{
listener = new TcpListener(IPAddress.Parse(hostName),portNumber);
}
listener.Start();
allsockets.Crear();
_start = true;
new Thread(new ThreadStart(ListenOnAccept)).Start();
}
}
private void ListenOnAccept()
{
while(_start)
{
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();
if (client != null)
allsockets.Add(client);
}
Thread.Sleep(500);//休息半秒钟
}
}

0.3里面使用Pending方法,检测当前是否有未处理的连接请求。如果有,就接受。因为Pending方法会立即返回,所以如果不加一个sleep的话,CPU的资源就会被它全部拿去了。不过,看到sleep,想必大家又发现了另外一个问题。这个设计,最快话,每秒不过能接受两个请求,似乎太寒酸了些吧!对,就是太寒酸了。于是乎,V0.4又诞生了。
private void ListenOnAccept()
{
bool bMore = false;//变化就在这里
while(_start)
{
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();
if (client != null)
{
allsockets.Add(client);
bMore = true;
}
}
else
{
bMore = false;
}

if (!bMore)
Thread.Sleep(500);//休息半秒钟
}
}

这次,我添加了一个标示bMore。被我“剽窃”的理论就是:如果当前出现了一个连接请求,那么很可能还会发生第二个连接请求。当有连接请求的时候,就不去sleep了,直到没有连接请求了,才进行每半秒一次的检测。

最后,还要添加上异常处理,比较完整的V0.5如下:
private void ListenOnAccept()
{
bool bMore = false;
while(_start)
{
try
{
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();
if (client != null)
{
allsockets.Add(client);
bMore = true;
}
}
else
{
bMore = false;
}
if (!bMore)
Thread.Sleep(500);
}
catch(System.Net.Sockets.SocketException se)
{
break;
}
}
}

剩下的比如日志,还有对异常信息的处理什么的,我就先不管了。

基本上,到这里后,start差不多了,下面开始stop。
stop?先stop一下。为什么要有stop呢?因为MSDN里面说要做close的。吃完饭总得有人刷碗啊!于是就有了stop。
老规矩,先上0.1,目标——调用close。
public void Stop()
{
if (_start)
{
_start = false;
foreach(TcpClient client in allsockets)
{
client.GetStream().Close();
client.Close();
}
listener.Stop();
allsockets.Clear();
}
}

到这里,简单的接收多个客户端请求的功能已经实现了。当然了,这个里面还是有很多问题的。比如hostName被写死,测试不方便等。这些问题,我会在下次解决,同时对框架做一些合理化的调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值