一步一步创建聊天程序2利用epoll来创建简单的聊天室

编程

 

 如图,这个是看视频时,最后的作业,除了客户端未使用select实现外,其它的要求都有简单实现。

服务端代码如下:

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <errno.h>

#include <sys/epoll.h>

#include <netinet/in.h>

#include <unistd.h>

#include<netinet/tcp.h>

#define MAX_LISTEN 10

#define EPOLL_SIZE 100

struct message

{

int target_id;

char buf[100];

};

struct user_password

{

char username[100];

char password[100];

};

//设置保活参数 keepalive_time保活时间,keepalive_intvl保活间隔,keepalive_probes保活探测数。

int set_keepalive(int sockfd,int keepalive_time, int keepalive_intvl, int keepalive_probes)

{

int optval;

socklen_t optlen= sizeof(optval);

optval=1;

if(-1==setsockopt(sockfd,SOL_SOCKET, SO_KEEPALIVE, &optval, optlen))

{

perror("setsockopt failture.

");

return -1;

}

optval=keepalive_probes;

if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT, &optval,optlen))

{

perror("setsockopt failture.

");

return -1;

}

optval=keepalive_intvl;

if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL, &optval,optlen))

{

perror("setsockopt failture.

");

return -1;

}

optval=keepalive_time;

if(-1==setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE, &optval, optlen))

{

perror("setsockopt failture

");

return -1;

}

return0;

}

void set_user_password(struct user_password users[100])

{

int fd=fopen("./password.txt","r");

if(fd==NULL)

{

perror("open password failed

");

return;

}

char buf[100];

int count=0;

int i=0;

while(feof(fd)==0)

{

fscanf(fd,"%s",buf);

if(count%2==0)

{

strcpy(users[i].username,buf);

count++;

}

else

{

strcpy(users[i++].password,buf);

count++;

}

}

fclose(fd);

}

int main(int argc,char * argv[])

{

//读取设定的用户名和密码

struct user_password users[100];

set_user_password(users);

for(int i=0;i<2;i++)

{

printf("user: %s, password: %s

",users[i].username,users[i].password);

}

struct sockaddr_in server_ip,customer_ip;

int err,sd;

sd=socket(AF_INET,SOCK_STREAM,0);

if(sd==-1)

{

perror("socket failed

");

close(sd);

return -1;

}

server_ip.sin_family=AF_INET;

server_ip.sin_port=htons(5678);

server_ip.sin_addr.s_addr=htonl(INADDR_ANY);

memset(server_ip.sin_zero,0,8);

err=bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));

if(err==-1)

{

perror("bind failed

");

close(sd);

return -1;

}

err=listen(sd,MAX_LISTEN);

if(err==-1)

{

perror("listen failed

");

close(sd);

return -1;

}

int epfd=epoll_create(EPOLL_SIZE);

if(epfd<0)

{

perror("epoll create failed

");

return -1;

}

printf("epoll created, epollfd=%d

",epfd);

struct epoll_event events[EPOLL_SIZE];

struct epoll_event event;

event.data.fd=sd;

event.events=EPOLLIN;

err=epoll_ctl(epfd,EPOLL_CTL_ADD,sd,&event);

if(err==-1)

{

perror("epoll add failed

");

return -1;

}

while(1)

{

int epoll_events_count=epoll_wait(epfd,events,EPOLL_SIZE,-1);

if(epoll_events_count<0)

{

perror("epoll wait failed

");

break;

}

printf("epoll_events_count= %d

",epoll_events_count);

for(int i=0;i<epoll_events_count;i++)

{

int sockfd=events[i].data.fd;

if(sockfd==sd)

{

int length=sizeof(struct sockaddr);

int client_fd=accept(sockfd,(struct sockaddr *)(&customer_ip),&length);

//用户名和密码检验

int flag=0;

char buf[100]="please input username and password ";

struct user_password login_user;

send(client_fd,buf,100,0);

recv(client_fd,&login_user,sizeof(struct user_password),0);

memset(buf,0,100);

for(int i=0;i<100;i++)

{

if((strcmp(users[i].username,login_user.username)==0)&&(strcmp(users[i].password,login_user.password)==0))

{

flag=1;

break;

}

}

if(flag)

{

err=set_keepalive(sockfd,120,20,3);

if(err!=0)

{

perror("set keep alive failed.

");

continue;

}

printf("USER %d online

",client_fd);

event.data.fd=client_fd;

event.events=EPOLLIN;

err=epoll_ctl(epfd,EPOLL_CTL_ADD,client_fd,&event);

if(err==-1)

{

perror("epoll add failed

");

return -1;

}

}

else

{

memset(buf,0,100);

strcpy(buf,"login failed

");

send(client_fd,buf,100,0);

}

}

else

{

struct message recv_message;

int bytes=recv(sockfd,&recv_message,sizeof(struct message),0);

if(bytes<0)

{

perror("recv failed

");

return -1;

}

elseif(bytes==0)

{

err=epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,events);

if(err==-1)

{

perror("epoll del failed

");

return -1;

}

printf("USER %d offline

",sockfd);

close(sockfd);

}

else

{

printf("recv message from cliend %d, buf: %s

",sockfd,recv_message.buf);

if(recv_message.target_id!=-1)//请求向客户端发送信息

{

err=send(recv_message.target_id,recv_message.buf,100,0);

if(err==-1)

{

perror("send failed

");

}

}

elseif(strcmp(recv_message.buf,"quit")==0)//用户输入quit,客户端推出。

{

printf("USER %d offline

",sockfd);

send(sockfd,recv_message.buf,100,0);

close(sockfd);

}

else

{

char cmd[100];

strcat(cmd,recv_message.buf);

strcat(cmd," >> test.txt");

int fd=fopen("./test.txt","w");

if(fd==NULL)

{

perror("clear file failed

");

continue;

}

close(fd);

printf("exec cmd: %s

",cmd);

system(cmd);

memset(cmd,0,100);

//将结果回送客户端

fd=fopen("./test.txt","r");

if(fd==NULL)

{

perror("open file failed

");

continue;

}

char buf[100];

while(feof(fd)==0)

{

int fread_ret=fread(buf,sizeof(char),sizeof(buf),fd);

send(sockfd,buf,100,0);

memset(buf,0,128);

}

fclose(fd);

}

}

}

}

}

return0;

}

客户端代码还是之前的版本,没有使用select实现:

#include <stdio.h>

#include <pthread.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

struct message

{

int target_id;

char buf[100];

};

struct user_password

{

char username[100];

char password[100];

};

int sd;

struct message send_message;

void * read_message(void * argv)

{

while(1)

{

//读服务器发来的消息

char revBuf[100];

read(sd,revBuf,100);

printf("recevice from server: %s",revBuf);

}

}

void * write_message(void * argv)

{

while(1)

{

printf("input message:

");

memset(send_message.buf,0,128);

send_message.target_id=-1;

scanf("%d %s",&send_message.target_id,send_message.buf);

write(sd,&send_message,sizeof(send_message));

sleep(3);

}

}

int main()

{

struct sockaddr_in server_ip,customer_ip;

int err;

sd=socket(AF_INET,SOCK_STREAM,0);

if(sd==-1)

{

printf("socket failed

");

close(sd);

return -1;

}

//server_ip初始化

server_ip.sin_family=AF_INET;

server_ip.sin_port=htons(5678);

server_ip.sin_addr.s_addr=htonl(INADDR_ANY);

//err=inet_aton("115.157.201.179",&server_ip.sin_addr.s_addr);

memset(server_ip.sin_zero,0,8);

err=connect(sd,(struct sockaddr *)(&server_ip),sizeof(server_ip));

if(err==-1)

{

printf("connect failed

");

close(sd);

return -1;

}

pid_t pid=fork();

if(pid==0)

{

while(1)

{

//读服务器发来的消息

//printf("read message:

");

char revBuf[100];

recv(sd,revBuf,100,0);

//read(sd,revBuf,100);

if(strcmp(revBuf,"quit")==0)

{

return0;

}

printf("recevice from server: %s

",revBuf);

}

}

int flag=0;

while(1)

{

printf("input message:

");

if(flag++==0)

{

struct user_password login_user;

scanf("%s %s",login_user.username,login_user.password);

err=send(sd,&login_user,sizeof(struct user_password),0);

if(err==-1)

{

printf("send failed

");

}

continue;

}

memset(send_message.buf,0,128);

send_message.target_id=-1;

scanf("%d %s",&send_message.target_id,send_message.buf);

//if(send_message.target_id!=-1&&(strcmp(send_message.buf,"")!=0))

//{

//err=send(sd,send_message.buf,100,0);

err=send(sd,&send_message,sizeof(send_message),0);

if(err==-1)

{

printf("send failed

");

}

//write(sd,&send_message,sizeof(send_message));

//}

if(strcmp(send_message.buf,"quit")==0)

{

printf("USER offline

");

close(sd);

return0;

}

send_message.target_id=-1;

memset(send_message.buf,0,sizeof(send_message.buf));

sleep(3);

}

close(sd);

return0;

}

 

以上是 一步一步创建聊天程序2利用epoll来创建简单的聊天室 的全部内容, 来源链接: utcz.com/z/511374.html

回到顶部