linux编程多用户聊天,Linux下poll函数实现多用户聊天

Client:

#define _GNU_SOURCE 1

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 64

int main()

{

const char *ip="127.0.0.1";

int port=12345;

struct sockaddr_in server_address;

bzero(&server_address,sizeof(server_address));

server_address.sin_family=AF_INET;

inet_pton(AF_INET,ip,&server_address.sin_addr);

server_address.sin_port=htons(port);

int sockfd=socket(PF_INET,SOCK_STREAM,0);

assert(sockfd!=0);

if(connect(sockfd,(struct sockaddr *)&server_address,sizeof(server_address))<0)

{

printf("connection failed\n");

close(sockfd);

return 1;

}

struct pollfd fds[2];

fds[0].fd=0;

fds[0].revents=0;

fds[1].fd=sockfd;

fds[1].events=POLLIN | POLLRDHUP;

fds[1].revents=0;

char read_buf[BUFFER_SIZE];

int pipefd[2];

int ret=pipe(pipefd);

assert(ret!=-1);

while(1)

{

ret=poll(fds,2,-1);

if(ret<0)

{

printf("poll failure\n");

break;

}

if(fds[1].revents&POLLRDHUP)

{

printf("server close the connection\n");

break;

}

else if(fds[1].revents&POLLIN)

{

memset(read_buf,'\0',BUFFER_SIZE);

recv(fds[1].fd,read_buf,BUFFER_SIZE-1,0);

printf("%s\n",read_buf);

}

if(fds[0].revents&POLLIN)

{

ret=splice(0,NULL,pipefd[1],NULL,32768,SPLICE_F_MORE | SPLICE_F_MOVE);

ret=splice(pipefd[0],NULL,sockfd,NULL,32768,SPLICE_F_MORE |SPLICE_F_MOVE);

}

}

close(sockfd);

return 0;

}

Server:

#define _GNU_SOURCE 1

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define USER_LIMIT 5

#define BUFFER_SIZE 64

#define FD_LIMIT 65535

struct client_data

{

struct 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()

{

const char *ip="127.0.0.1";

int port=12345;

int ret=0;

int i,j;

struct sockaddr_in address;

bzero(&address,sizeof(address));

address.sin_family=AF_INET;

inet_pton(AF_INET,ip,&address.sin_addr);

address.sin_port=htons(port);

// address.sin_addr.s_addr=INADDR_ANY;

int listenfd=socket(PF_INET,SOCK_STREAM,0);

assert(listenfd>=0);

ret=bind(listenfd,(struct sockaddr *)&address,sizeof(address));

assert(ret!=-1);

ret=listen(listenfd,5);

assert(ret!=-1);

struct client_data* users=(struct client_data*) calloc(FD_LIMIT,sizeof(struct client_data));

struct pollfd fds[USER_LIMIT+1];

int user_counter=0;

for(i=1;i<=USER_LIMIT;++i)

{

fds[i].fd=-1;

fds[i].events=0;

}

fds[0].fd=listenfd;

fds[0].events=POLLIN | POLLERR;

fds[0].revents=0;

while(1)

{

printf("{\n");

ret=poll(fds,user_counter+1,-1);

printf("}\n");

if(ret<0)

{

printf("poll failure\n");

break;

}

for(i=0;i

{

if((fds[i].fd==listenfd)&&(fds[i].revents&POLLIN))

{

struct sockaddr_in client_address;

socklen_t client_addrlengh=sizeof(client_address);

int connfd=accept(listenfd,(struct sockaddr *)&client_address,&client_addrlengh);

if(connfd<0)

{

printf("errno is:%d\n",errno);

continue;

}

if(user_counter>=USER_LIMIT)

{

const char *info="too many users\n";

printf("%s",info);

send(connfd,info,strlen(info),0);

close(connfd);

continue;

}

user_counter++;

users[connfd].address=client_address;

setnonblocking(connfd);

fds[user_counter].fd=connfd;

fds[user_counter].events=POLLIN |POLLRDHUP|POLLERR;

fds[user_counter].revents=0;

printf("comes a new user,now have %d users\n",user_counter);

}

else if(fds[i].revents&POLLERR)

{

printf("get an error from %d \n",fds[i].fd);

char errors[100];

memset(errors,'\0',100);

socklen_t length=sizeof(errors);

if(getsockopt(fds[i].fd,SOL_SOCKET,SO_ERROR,&errors,&length)<0)

{

printf("get socket option failed\n");

}

continue;

}

else if(fds[i].revents&POLLRDHUP)

{

users[fds[i].fd]=users[fds[user_counter].fd];

close(fds[i].fd);

fds[i]=fds[user_counter];

i--;

user_counter--;

printf("a client left\n");

}

else if(fds[i].revents&POLLIN)

{

int connfd=fds[i].fd;

memset(users[connfd].buf,'\0',BUFFER_SIZE-1);

ret=recv(connfd,users[connfd].buf,BUFFER_SIZE-1,0);

if(ret<0)

{

if(errno!=EAGAIN)

{

close(connfd);

users[fds[i].fd]=users[fds[user_counter].fd];

fds[i]=fds[user_counter];

i--;

user_counter--;

}

}

else if(ret==0)

{

}

else

{

for(j=1;j<=user_counter;++j)

{

if(fds[j].fd==connfd)

{

continue;

}

fds[j].events |=~POLLIN;

fds[j].events |=POLLOUT;

users[fds[j].fd].write_buf=users[connfd].buf;

}

}

}

else if(fds[i].revents&POLLOUT)

{

int connfd=fds[i].fd;

if(!users[connfd].write_buf)

{

continue;

}

ret=send(connfd,users[connfd].write_buf,strlen(users[connfd].write_buf),0);

users[connfd].write_buf=NULL;

fds[i].events |=~POLLOUT;

fds[i].events |=POLLIN;

}

}

}

free(users);

close(listenfd);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值