高级IO复用应用:聊天室程序

2014-11-23 23:34:03 · 作者: · 浏览: 4
简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户。这里采用IO复用poll技术。客户端采用了splice零拷贝。服务端采用了空间换时间(分配超大的用户数据数组,然后通过用户连接的文件描述符即可以索引到用户数据)
客户端程序:
#define _GNU_SOURCE 1//为了支持POLLRDHUP事件  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#define BUFFER_SIZE 64  
using namespace std;  
int main(int argc,char* argv[]){  
    if(argc<=2){  
        cout<<"argc<=2"<=0);  
    if(connect(sockfd,(struct sockaddr*)&address,sizeof(address))<0){  
        cout<<"connect error"< 
  

服务端程序:
#define _GNU_SOURCE 1//支持POLLRDHUP事件  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#define USER_LIMIT 5//最大用户数,限制用户是为了提高poll性能  
#define BUFFER_SIZE 64//缓冲区大小  
#define FD_LIMIT 65535//文件描述符限制  
using namespace std;  
struct client_data{//客户数据:客户端socket地址、待写到客户端的数据位置、从客户端读入的数据。用于服务端与客户端高速交互  
    sockaddr_in address;  
    char* write_buf;  
    char buf[BUFFER_SIZE];  
};  
int setnonblocking(int fd){//设置文件描述符为非阻塞  
    int old_option=fcntl(fd,F_GETFL);  
    int new_option=old_option|O_NONBLOCK;  
    fcntl(fd,F_SETFL,new_option);  
    return old_option;  
}  
int main(int argc,char* argv[]){  
    if(argc<=2){  
        cout<<"argc<=2"<=0);  
    ret=bind(listenfd,(struct sockaddr*)&address,sizeof(address));  
    assert(ret!=-1);  
    ret=listen(listenfd,5);  
    assert(listenfd!=-1);  
    client_data* users=new client_data[FD_LIMIT];//分配一个超大的用户数据数组,当用户与服务器连接产生的连接描述符可以作为数组下标迅速索引到用户数据  
    pollfd fds[USER_LIMIT+1];//pollfd结构体数组,每个用户注册一组poll事件  
    int user_count=0;  
    for(int i=0;i<=USER_LIMIT;i++){//初始化poll事件  
        fds[i].fd=-1;//不可能的描述符  
        fds[i].events=0;  
    }  
    fds[0].fd=listenfd;  
    fds[0].events=POLLIN|POLLERR;//监听端口注册可读和错误事件  
    fds[0].revents=0;  
    while(1){  
        ret=poll(fds,user_count+1,-1);//无限期等待注册事件就绪  
        if(ret<0){  
            cout<<"poll error"<
=USER_LIMIT){//已连接的用户数大于最大用户数,则不允许连接 const char* info="too many users,you can't connect\n"; cout<

}//这里会出现一个问题就是若某个用户A频繁发送消息给服务端服务端,再转发给其它用户,此期间其它用户也有话要说,则服务端可读事件全被A用户占领了,其它用户全是POLLOUT事件