论文部分内容阅读
摘要:介绍了在Linux上用socket编程来设计并实现一个简单聊天室。首先选择了服务器的轮询工作方式,以满足多个用户进程的连接;然后从数据结构、模块开发和源码实现三个方面详细分析了聊天室的实现;最后将该聊天室与传统聊天室进行了比较,并指出该聊天室的优势所在。
关键词:聊天室; Linux ;socket ;数据结构
中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)21-30442-03
The Design and Accomplishment of the Simple Chat-room Based on Socket
ZHOU Liu-jun1,2, WU Jin-lei1
(1.College of Information and Electrical Engineering of CUMT, Xuzhou 221008, China;2.Xuzhou Institute of Architectural Technology, Xuzhou 221008 China)
Abstract: How to design and accomplish a simple chat room with socket in linux is introduced is introduced in this paper. In order to meet many connections of user process, the poll woking of server is selected firstly. Then accomplishment of the simple chat-room is analyzed particularly in the facets of data structure, module development and codeaccomplishment. According to the comparison of the chat room and the traditional chat room, advantage of the chat room is shown.
Key words: chat room; linux; socket; data structure
1 引言
Socket聊天室与传统的CGI聊天室工作原理有很大的不同,其基本原理是抛开OGI和WWW服务器,根据HTML规范,接收到浏览器的请求以后,模仿WWW服务器的响应,将聊天内容发回浏览器。在浏览器看来就像浏览一个巨大的页面一样始终处于页面联接状态, 这就是一个专门的聊天服务器,一个简化了的WWW服务器。这样相比CGI方式来说,Socket聊天室的优点就很明显:不需要专门的WWW服务器,避开耗时的CGI 过程;如果使用单进程服务器,就不需要每次产生新进程;数据交换完全在内存中进行,不用读写文件;不需要定时刷新,减少屏幕的闪烁,减少对服务器的请求次数。
linux作为一个优秀的操作系统,具有成本低、性能高、稳定性和源代码开放等特点,并吸收了Unix的20年的发展经验,内核精炼而稳定。鉴于socket聊天室和linux系统的优点,本文即在linux下,利用socket编程实现一个简单的聊天室。
2 服务器设计
聊天室采用client/server结构,在server进入listen状态之后,由于已有多个用户在线,所以程序需要同时对这些用户进行操作,并在它们之间实现信息交换。这在实现上称为I/O多路复用技术。下面即为几种常用的多路复用技术:
2.1 多路复用技术
多路复用一般有以下几种技术:
1)子进程技术。应用多个子进程,每一个对一个单工阻塞方式通信。所有子进程通过IPC和父进程进行通信。父进程掌管所有信息。这种方式的缺点是实现复杂,而且由于IPC在各个操作系统平台上不完全一致,会导致可移植性降低。
2)信号驱动的异步I/O技术。首先,异步I/O是基于信号机制的,并不可靠。其次,单一的信号不足以提供更多的信息来源。还是需要辅助以其他的手段,实现有很高的难度。
3)select()技术。在BSD中提供了一种可以对多路I/O进行阻塞式查询的方法—select()。它提供同时对多个I/O描述符进行阻塞式查询的方法。
4)非阻塞通信技术:将文件管道通过fcntl()设为非阻塞通信方式,每隔一段时间对他们实行一次轮询,以判断是否可以进行读写操作。这种技术实现简单,该聊天室即采用此种I/O复用技术,下面对其进行详细的介绍。
2.2非阻塞通信技术
对一个文件描述符指定的文件或设备, 有两种工作方式:阻塞与非阻塞。对于非阻塞状态,如果没有东西可读,或者不可写,读写函数马上返回,而不会等待。缺省情况下,文件描述符处于阻塞状态。
在实现聊天室时,server 轮流查询与各client 建立 socket,一旦可读就将该socket中的字符读出并向其他client 发送。同时server 还要随时查看是否有新的client 试图建立连接,如果server在任何一个地方阻塞了,其他client发送的内容就会受到影响,新client 试图建立连接也会受到影响。因此,我们使用fcntl()将该文件描述符变为非阻塞方式,对是否有新连接及是否可读的判断都是非阻塞的,服务器的每次判断都会马上返回。这样任何一个client向server发送字符或者试图建立新连接,都不会对其他client的活动造成影响。
3 聊天室实现
下面从数据结构、模块开发和源码实现三个方面分析该聊天室的实现过程。
3.1 主要数据结构
本文用struct chat_struct chater[MAXUSERS]结构数组来记录系统中的每一个用户的重要信息:指向用户连接的套接字描述符、用户的数据缓冲区、用户的指令等。结构的定义如下:
各成员含义如下:
#define MAXUSERS 20
Struct chat_struct
{
int sock_fd;
char user_id[20];
struct client_cmd
{
int cmd_type;
char user_id[20];
}cmd;
int next_char;
int data_pos;
char buffer[MAXLINE];
int slot_status;
}chater[MAXUSERS];
sock_fd:指向该用户连接的套接字描述符。
user_id:用户的用户名,用于标志用户的身份。
next_char:用于指示用户数据缓冲区中的写位置,即写指针。
data_pos:用于指示用户指令中的消息的内容。
slot_status:槽位的状态,标识槽位是否被使用。
struct client_cmd cmd:将用户的数据记录分析后,把分析的结果存放在该结构中。用户的指令类型使用常量定义,这样的设计,有利于对系统进行进一步的扩充。
3.2 模块的划分
可以将应用划分为4个功能模块:用户状态检测模块、数据记录分析处理模块、结构访问模块和通信模块。
1)用户状态检测模块用于检测系统中各个用户的状态。状态的划分应当根据应用的需求来确定,用户状态可分为3种:
①用户已经输入了一个数据记录,等待服务器处理。服务器读入数据记录,并调用数据记录分析处理模块来处理数据记录。
②用户退出系统,等待服务器清除用户槽位。服务器调用结构访问模块将用户的槽位释放。
③用户的其他行为被列为第3种状态。服务器只是读入数据,由于没有遇到数据记录的边界,所以它将在后面转化成状态①或②。
2)数据记录分析模块,对读取的数据记录进行分析,如果指令正确,则处理指令。如果指令错误,进行出错处理。
4 总结
基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室。这种聊天室的特点很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新,而是当有人发言时,屏幕上才会出现新聊天内容。也不同于CGI聊天室由客户端浏览器定时请求聊天内容,而是由聊天服务器软件向客户浏览器主动发送信息。这种聊天室可以容纳许多人而性能不会明显降低,因此基于socket的聊天室较传统的聊天室有很大优势。
参考文献:
[1] 邹思轶.嵌入式linux设计与应用[M].北京:清华大学出版社,2002.
[2] 任永铮.Linux C程序员指南[M].北京:国防工业出版社,2000.
[3] 林宇,郭凌云.Linux网络编程[M].北京:人民邮电出版社,2000.
关键词:聊天室; Linux ;socket ;数据结构
中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)21-30442-03
The Design and Accomplishment of the Simple Chat-room Based on Socket
ZHOU Liu-jun1,2, WU Jin-lei1
(1.College of Information and Electrical Engineering of CUMT, Xuzhou 221008, China;2.Xuzhou Institute of Architectural Technology, Xuzhou 221008 China)
Abstract: How to design and accomplish a simple chat room with socket in linux is introduced is introduced in this paper. In order to meet many connections of user process, the poll woking of server is selected firstly. Then accomplishment of the simple chat-room is analyzed particularly in the facets of data structure, module development and codeaccomplishment. According to the comparison of the chat room and the traditional chat room, advantage of the chat room is shown.
Key words: chat room; linux; socket; data structure
1 引言
Socket聊天室与传统的CGI聊天室工作原理有很大的不同,其基本原理是抛开OGI和WWW服务器,根据HTML规范,接收到浏览器的请求以后,模仿WWW服务器的响应,将聊天内容发回浏览器。在浏览器看来就像浏览一个巨大的页面一样始终处于页面联接状态, 这就是一个专门的聊天服务器,一个简化了的WWW服务器。这样相比CGI方式来说,Socket聊天室的优点就很明显:不需要专门的WWW服务器,避开耗时的CGI 过程;如果使用单进程服务器,就不需要每次产生新进程;数据交换完全在内存中进行,不用读写文件;不需要定时刷新,减少屏幕的闪烁,减少对服务器的请求次数。
linux作为一个优秀的操作系统,具有成本低、性能高、稳定性和源代码开放等特点,并吸收了Unix的20年的发展经验,内核精炼而稳定。鉴于socket聊天室和linux系统的优点,本文即在linux下,利用socket编程实现一个简单的聊天室。
2 服务器设计
聊天室采用client/server结构,在server进入listen状态之后,由于已有多个用户在线,所以程序需要同时对这些用户进行操作,并在它们之间实现信息交换。这在实现上称为I/O多路复用技术。下面即为几种常用的多路复用技术:
2.1 多路复用技术
多路复用一般有以下几种技术:
1)子进程技术。应用多个子进程,每一个对一个单工阻塞方式通信。所有子进程通过IPC和父进程进行通信。父进程掌管所有信息。这种方式的缺点是实现复杂,而且由于IPC在各个操作系统平台上不完全一致,会导致可移植性降低。
2)信号驱动的异步I/O技术。首先,异步I/O是基于信号机制的,并不可靠。其次,单一的信号不足以提供更多的信息来源。还是需要辅助以其他的手段,实现有很高的难度。
3)select()技术。在BSD中提供了一种可以对多路I/O进行阻塞式查询的方法—select()。它提供同时对多个I/O描述符进行阻塞式查询的方法。
4)非阻塞通信技术:将文件管道通过fcntl()设为非阻塞通信方式,每隔一段时间对他们实行一次轮询,以判断是否可以进行读写操作。这种技术实现简单,该聊天室即采用此种I/O复用技术,下面对其进行详细的介绍。
2.2非阻塞通信技术
对一个文件描述符指定的文件或设备, 有两种工作方式:阻塞与非阻塞。对于非阻塞状态,如果没有东西可读,或者不可写,读写函数马上返回,而不会等待。缺省情况下,文件描述符处于阻塞状态。
在实现聊天室时,server 轮流查询与各client 建立 socket,一旦可读就将该socket中的字符读出并向其他client 发送。同时server 还要随时查看是否有新的client 试图建立连接,如果server在任何一个地方阻塞了,其他client发送的内容就会受到影响,新client 试图建立连接也会受到影响。因此,我们使用fcntl()将该文件描述符变为非阻塞方式,对是否有新连接及是否可读的判断都是非阻塞的,服务器的每次判断都会马上返回。这样任何一个client向server发送字符或者试图建立新连接,都不会对其他client的活动造成影响。
3 聊天室实现
下面从数据结构、模块开发和源码实现三个方面分析该聊天室的实现过程。
3.1 主要数据结构
本文用struct chat_struct chater[MAXUSERS]结构数组来记录系统中的每一个用户的重要信息:指向用户连接的套接字描述符、用户的数据缓冲区、用户的指令等。结构的定义如下:
各成员含义如下:
#define MAXUSERS 20
Struct chat_struct
{
int sock_fd;
char user_id[20];
struct client_cmd
{
int cmd_type;
char user_id[20];
}cmd;
int next_char;
int data_pos;
char buffer[MAXLINE];
int slot_status;
}chater[MAXUSERS];
sock_fd:指向该用户连接的套接字描述符。
user_id:用户的用户名,用于标志用户的身份。
next_char:用于指示用户数据缓冲区中的写位置,即写指针。
data_pos:用于指示用户指令中的消息的内容。
slot_status:槽位的状态,标识槽位是否被使用。
struct client_cmd cmd:将用户的数据记录分析后,把分析的结果存放在该结构中。用户的指令类型使用常量定义,这样的设计,有利于对系统进行进一步的扩充。
3.2 模块的划分
可以将应用划分为4个功能模块:用户状态检测模块、数据记录分析处理模块、结构访问模块和通信模块。
1)用户状态检测模块用于检测系统中各个用户的状态。状态的划分应当根据应用的需求来确定,用户状态可分为3种:
①用户已经输入了一个数据记录,等待服务器处理。服务器读入数据记录,并调用数据记录分析处理模块来处理数据记录。
②用户退出系统,等待服务器清除用户槽位。服务器调用结构访问模块将用户的槽位释放。
③用户的其他行为被列为第3种状态。服务器只是读入数据,由于没有遇到数据记录的边界,所以它将在后面转化成状态①或②。
2)数据记录分析模块,对读取的数据记录进行分析,如果指令正确,则处理指令。如果指令错误,进行出错处理。
4 总结
基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室。这种聊天室的特点很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新,而是当有人发言时,屏幕上才会出现新聊天内容。也不同于CGI聊天室由客户端浏览器定时请求聊天内容,而是由聊天服务器软件向客户浏览器主动发送信息。这种聊天室可以容纳许多人而性能不会明显降低,因此基于socket的聊天室较传统的聊天室有很大优势。
参考文献:
[1] 邹思轶.嵌入式linux设计与应用[M].北京:清华大学出版社,2002.
[2] 任永铮.Linux C程序员指南[M].北京:国防工业出版社,2000.
[3] 林宇,郭凌云.Linux网络编程[M].北京:人民邮电出版社,2000.