linux聊天服务器开发
由于工作需要,最近开发了这么样的一个服务器端程序。严格意义上面来讲,这个程序并不是平常聊天的服务器程序,它是一个游戏系统中的广播服务器处理程序。不过只需要稍微做一些修改的话,他就可以成为一个聊天的服务器。
首先简单地介绍一下功能(希望我们的程序员不要觉得麻烦),游戏已经上线了,根据设想,我们还想做一个广播系统,即游戏里面的用户发生了一些事件,我们在php的代码中,将这些事件经过后端的服务器发到前端的flash页面上,让所有的用户都知道这样一件事情。
这个就是简单的程序运行示意图,linux服务器主要处理的就是从php程序中接受数据,让后将这些数据推送到前台的页面上去。
这样的一个系统,我采用的是socket来实现它,今天我们不介绍php是如何处理socket的,前面已经有相关的文件介绍,另外,对于数据传输使用的协议,这里也不做介绍,这个东西只要我们对服务器和php程序做统一的规定就好了。我们的重点是总结一下这个广播后台的实现过程:
我们简单地看看使用socket服务器需要做那些处理:
1。加载socket 协议,
2。创建一个socket对象,
3。将该socket bind到一个端口,
4。监听该端口的相应(使用listener),
5。接受客户端的socket,
6。建立数据库传输。
大部分socket编程都会使用上面的结构,我们这里也是,使用的tcp协议。对于我们的程序,这里有个特殊的要求,我们不是面对一对一的数据传输,我们只是从一个地方接受数据,但是我们要将这个数据推送到前面的很多客户端上面去,所以我们的客户端连接讲是一个数组。在我的程序里面我使用这样的结构
typedef struct CLIENT {
int fd;
struct sockaddr_in addr;
}CLIENT;
CLIENT client[FD_SETSIZE]; //后面的FD_SETSIZE设置为1024
while (1)
{
confd =accept(slisten, (struct sockaddr*)&addr,&len)) == -1;
if(confd)
{
for (i=0; i<FD_SETSIZE; i++)
{
if(client[i].fd<0)
{
client[i].fd = confd;
client[i].addr = addr;
}
}
}
}
上面的代码就是将这样的一个client填满,如果有些客户端断掉了,我们再使用新来的连接将其补上。
上面说了,这个程序还要接受php程序的数据,那么就必须使用到recv 和send函数,但是我们知道,这些函数是阻塞I/O,如果没有数据进来的话,程序就会停留在这个地方,这样需要推送的数据自然发送不了(大家可以自己动手实现一下,)。要解决这样一个问题,那就必须使用非阻塞式编程啦。
在这里我使用了select 函数,具体的使用详细地介绍,大家可以上网去查查:
fd_set 是select 的一个基本结构,这里我们定义
fd_set allset, rset;
FD_ZERO(&allset); //初始化
FD_SET(slisten, &allset); //将服务器的socket放到select中
maxfd = slisten;
nready = select(maxfd + 1, &rset, NULL, NULL, &tv); //注意第一个参数一定要加一, 这个函数很重要,在使用的使用查清楚
我们会根据这个nready的值来做不同的处理:
if(nready==0) //超时
else if(nready < 0) //出错
else
{
//说明有数据传输
//使用FD_ISSET来判断是哪一个有反映,例如有新的接口,接受数据等等
}
这里再提一个问题,刚才讲了一个程序只能处理1024个的连接,那如果用户的数目大于1024, 需要怎么处理了?