失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Linux ubuntu18.04下socket聊天室 私聊 群聊

Linux ubuntu18.04下socket聊天室 私聊 群聊

时间:2023-03-29 18:30:42

相关推荐

Linux ubuntu18.04下socket聊天室 私聊 群聊

这个聊天室写出来也有一段时间了

先来几张效果图

进入界面

登录成功界面

群聊时三个客户端界面

群聊时服务器打印信息

mysql数据库里存放的用户信息

首先要懂几个东西就是socket网络编程mysql的增删改查多线程IO复用的一点皮毛就没了

首先 socket网络编程就下面几个步骤

定义绑定 设置最大监听数 监听等待连接 收发信息

还有就是mysql的简单操作

create database 数据库名 ------新建数据库show create database ------查看数据库定义drop database 数据库名 ------删除数据库use 数据库名 ------操作对象切换create table … ------创建表

然后直接贴代码吧

server.cpp

#include<iostream>#include<sys/types.h>#include<sys/socket.h>#include<sys/select.h>#include<string.h>#include<string>#include<stdio.h>#include<stdlib.h>#include<arpa/inet.h>#include<unistd.h>#include<vector>#include<memory.h>#include<pthread.h>#include<signal.h>#include<mysql/mysql.h>#include<stack>#include<algorithm>#include<sstream>using namespace std;#define SER_PORT 12345struct user{char name[20];char sex[3];char age[4];char phonenumber[12];char account[12];char password[12];int fd_s;};vector<user> infos;struct Sockfd{int sockfd_1;bool all_chat_flag;};vector<Sockfd> sockfdd;class Database{public:Database();~Database();void add();void Select();void conn();};MYSQL mysql;class server:public Database{public:int all_chat(int fd,char id[12]);//群聊 转发给每个套接字int private_chat(int fd,char id[12]);//私聊 转发给指定套接字int read_info(int fd); //查看他人信息void deal_client(int &fd); int check_account(char id[12],char pwd[12]); //账号密码验证int add_user(int fd); //新用户注册private:user users;};void * papa(void *arg);void handle_pipe(int sig){}int main(){Database bases;bases.conn();bases.Select();struct sigaction sa;sa.sa_handler=handle_pipe;sigemptyset(&sa.sa_mask);sa.sa_flags=0;sigaction(SIGPIPE,&sa,NULL);int sockfd=socket(AF_INET,SOCK_STREAM,0); //设置套接字if(sockfd==-1){perror("sockfd error");return -1;}struct sockaddr_in ser_addr; int ret;memset(&ser_addr,0,sizeof(ser_addr));ser_addr.sin_family=AF_INET; //结构体初始化ser_addr.sin_port=htons(SER_PORT);ser_addr.sin_addr.s_addr=inet_addr("127.0.0.1");int opt=1;setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));ret=bind(sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr)); //绑定if(ret==-1){perror("bind error");return -1;}ret=listen(sockfd,128); //设置最大侦听数if(ret==-1){perror("listen error");}int newfd;pthread_t id; struct sockaddr_in cli_addr;socklen_t len=sizeof(cli_addr);while(1){memset(&cli_addr,0,sizeof(cli_addr));newfd=accept(sockfd,(struct sockaddr *)&cli_addr,&len); //阻塞等待连接if(newfd==-1){perror("accept error");return -1;}printf("端口 %d 已加入连接\n",newfd);pthread_create(&id,NULL,papa,&newfd); //创建线程pthread_detach(id);//清除线程}bases.add();return 0;}Database::Database(){}Database::~Database(){}void Database::conn(){mysql_init(&mysql);if(!mysql_real_connect(&mysql,"localhost","root","root","testdb",12345,NULL,0)){cout<<"connect fial\n";}}void Database::add(){bool ret=false;string sql;for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){sql="INSERT INTO client(sex,age,phonenumber,account,password) VALUES(";sql.append("'");sql.append(iter->sex);sql.append("'");sql.append(",");sql.append("'");sql.append(iter->age);sql.append("'");sql.append(",");sql.append("'");sql.append(iter->phonenumber);sql.append("'");sql.append(",");sql.append("'");sql.append(iter->account);sql.append("'");sql.append(",");sql.append("'");sql.append(iter->password);sql.append("'");sql.append(");");ret=mysql_query(&mysql,sql.c_str());}return;}void Database::Select(){MYSQL_ROW row;user mm;MYSQL_FIELD* field =NULL;MYSQL_RES* result;string sql="SELECT * FROM client";mysql_query(&mysql,sql.c_str());result=mysql_store_result(&mysql);for(int i=0;i<mysql_num_fields(result);i++){field=mysql_fetch_field_direct(result,i);}row=mysql_fetch_row(result);while(row!=NULL){strcpy(mm.sex,row[0]);strcpy(mm.age,row[1]);strcpy(mm.phonenumber,row[2]);strcpy(mm.account,row[3]);strcpy(mm.password,row[4]);infos.push_back(mm);row=mysql_fetch_row(result);}return;}void * papa(void *arg){int fd=*(int * )arg;server user_1;user_1.deal_client(fd);}void server::deal_client(int &fd){ //处理客户端char recvbuf[1024]={0};char recvbuf1[1024]={0};char sendbuf[1024]={0};int ret;while(1){memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;5;1m[系统消息]:\033[0m\n\033[36;1;4m欢迎加入IKUN粉丝俱乐部 功能如下:\n\t1.登录\n\t2.注册\n\t3.退出\033[0m"); //连接成功欢迎语ret=send(fd,sendbuf,strlen(sendbuf),0); if(ret==-1){perror("send error");return ;}memset(recvbuf,0,sizeof(recvbuf));ret=recv(fd,recvbuf,sizeof(recvbuf),0);if(ret==-1){perror("recv error");return;}if(strcmp(recvbuf,"1")==0){memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;5;1m[系统消息:]\033[0m\n\033[36;1m请输入您的账号:\033[0m");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}memset(recvbuf,0,sizeof(recvbuf));ret=recv(fd,recvbuf,sizeof(recvbuf),0);if(ret==-1){perror("recv error");return;}memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[36;1m请输入密码:\033[0m");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}memset(recvbuf1,0,sizeof(recvbuf1));ret=recv(fd,recvbuf1,sizeof(recvbuf1),0);if(ret==-1){perror("recv error");return;}if(check_account(recvbuf,recvbuf1)!=1){ //登录验证memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m您的账号或密码不正确\n\033[0m");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}}else{memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m登录成功 欢迎\n\033[0m");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){if(strcmp(iter->account,recvbuf)==0){iter->fd_s=fd;users=(*iter);}}Sockfd a;a.all_chat_flag=false;a.sockfd_1=fd;sockfdd.push_back(a);while(1){memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[36;1;4m请输入您的选择:\n\t1.加入群聊 \n\t2.私聊 \n\t3.查看他人信息 \n\t4.退出");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}memset(recvbuf1,0,sizeof(recvbuf1));ret=recv(fd,recvbuf1,sizeof(recvbuf1),0);if(ret==-1){perror("recv error");return ;}if(strcmp(recvbuf1,"1")==0){all_chat(fd,recvbuf);}else if(strcmp(recvbuf1,"2")==0){private_chat(fd,recvbuf);}else if(strcmp(recvbuf1,"3")==0){read_info(fd);}else if(strcmp(recvbuf1,"4")==0){break;}else{continue;}}}}else if(strcmp(recvbuf,"2")==0){add_user(fd);add();}else if(strcmp(recvbuf,"3")==0){memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"再见!");ret=send(fd,sendbuf,strlen(sendbuf),0);if(ret==-1){perror("send error");return ;}printf("端口 %d 已断开连接\n",fd);break;}else{continue;}}close(fd);}int server::check_account(char id[12],char pwd[12]){for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){if((strcmp(id,iter->account)==0)&&(strcmp(pwd,iter->password)==0)){return 1;}}return 0;}int server::all_chat(int fd,char id[12]){ //群聊char sendbuf[1024];char recvbuf[1024];time_t timep;int ret;time(&timep);strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n欢迎加入IKUN大群畅聊\n\t输入quit退出群聊");for(vector<Sockfd>::iterator iter=sockfdd.begin();iter!=sockfdd.end();iter++){if(fd==iter->sockfd_1){iter->all_chat_flag=true;break;}}ret=send(fd,sendbuf,sizeof(sendbuf),0);if(ret==-1){perror("send error");}while(1){memset(recvbuf,0,sizeof(recvbuf));int ret;ret=recv(fd,recvbuf,sizeof(recvbuf),0);if(ret==0)break;if(strcmp(recvbuf,"quit\0")==0){for(vector<Sockfd>::iterator iter=sockfdd.begin();iter!=sockfdd.end();iter++){if(fd==iter->sockfd_1){iter->all_chat_flag=false;break;}}break;}printf("[%s] 说:%s\n",id,recvbuf);for(vector<Sockfd>::iterator iter=sockfdd.begin();iter!=sockfdd.end();iter++){if(fd!=iter->sockfd_1&&(iter->all_chat_flag==true)){memset(sendbuf,0,sizeof(sendbuf));sprintf(sendbuf,"\033[34;1m%s[%s] 说\033[0m: %s",ctime(&timep),id,recvbuf);send(iter->sockfd_1,sendbuf,strlen(sendbuf),0);}}}return 0;}int server::private_chat(int fd,char id[12]){int flag=1;char recvbuf[1024];char sendbuf[1024];char str[1024];int ret=0;time_t timep;time(&timep);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m请输入需要私聊好友的ID:\n输入quit结束本次聊天");send(fd,sendbuf,strlen(sendbuf),0);memset(recvbuf,0,sizeof(recvbuf));recv(fd,recvbuf,sizeof(recvbuf),0);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m您与您的好友已建立私聊通道");send(fd,sendbuf,strlen(sendbuf),0);strcpy(str,recvbuf);for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){if(strcmp(iter->account,str)==0){ret=iter->fd_s;}}while(1){memset(recvbuf,0,sizeof(recvbuf));if(strcmp(recvbuf,"quit\0")==0){break;}recv(fd,recvbuf,sizeof(recvbuf),0);memset(sendbuf,0,sizeof(sendbuf));sprintf(sendbuf,"\033[33;1m[%s] [%s]说\033[0m:%s",ctime(&timep),id,recvbuf);printf("%s\n",sendbuf);send(ret,sendbuf,strlen(sendbuf),0);}return 0;}int server::read_info(int fd){char recvbuf[1024];char sendbuf[1024];char name_2[20];char sex_2[3];char age_2[4];char phonenumber_2[12];char account_2[12];bool flag=false;system("clear");memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m请输入您需要查询信息的用户ID:");send(fd,sendbuf,strlen(sendbuf),0);memset(recvbuf,0,sizeof(recvbuf));recv(fd,recvbuf,sizeof(recvbuf),0);for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){if(strcmp(iter->account,recvbuf)==0){flag=true;memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m您所查询的用户信息如下\n\t\033[0m姓名:");send(fd,sendbuf,strlen(sendbuf),0);send(fd,iter->name,strlen(iter->name),0);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\n\t[性别]:");send(fd,sendbuf,strlen(sendbuf),0);send(fd,iter->sex,strlen(iter->sex),0);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\n\t[年龄]:");send(fd,sendbuf,strlen(sendbuf),0);send(fd,iter->age,strlen(iter->age),0);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\n\t[联系电话]:");send(fd,sendbuf,strlen(sendbuf),0);send(fd,iter->phonenumber,strlen(iter->phonenumber),0);memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\n\t[账户号码]:");send(fd,sendbuf,strlen(sendbuf),0);send(fd,iter->account,strlen(iter->account),0);send(fd,"\n",1,0);}}if(!flag){memset(sendbuf,0,sizeof(sendbuf));strcpy(sendbuf,"\033[31;1;5m[系统消息]:\033[0m\n未找到您查询的用户 即将返回上一页\n");send(fd,sendbuf,strlen(sendbuf),0);}return 0;}int server::add_user(int fd){int leap=0;char str[256];char str1[256];user adds;memset(str,0,sizeof(str));memset(str1,0,sizeof(str1));strcpy(str,"\033[31;1;5m[系统消息]:\033[0m\n\033[36;1;4m请输入11位以下账号进行注册:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(str1,str);for(vector<user>::iterator iter=infos.begin();iter!=infos.end();iter++){if(strcmp(str,iter->account)==0){memset(str,0,sizeof(str));strcpy(str,"\033[31;1;5m[系统消息]\033[0m:\n账号重复\n");send(fd,str,strlen(str),0);return -1;}}strcpy(adds.account,str1);memset(str,0,sizeof(str));strcpy(str,"请输入密码:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(adds.password,str);memset(str,0,sizeof(str));strcpy(str,"请设置你的昵称:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(adds.name,str);memset(str,0,sizeof(str));strcpy(str,"请输入你的性别:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(adds.sex,str);memset(str,0,sizeof(str));strcpy(str,"请输入你的年龄:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(adds.age,str);memset(str,0,sizeof(str));strcpy(str,"请输入你的联系电话:");send(fd,str,strlen(str),0);memset(str,0,sizeof(str));recv(fd,str,sizeof(str),0);strcpy(adds.phonenumber,str);infos.push_back(adds);return 0;}

client.cpp

#include<iostream>#include<stdio.h>#include<errno.h>#include<string.h>#include<sys/types.h>#include<netinet/in.h>#include<sys/socket.h>#include<sys/wait.h>#include<sys/time.h>#include<arpa/inet.h>#include<unistd.h>using namespace std;#define SER_PORT 12345int main(){int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){perror("socket erro");exit(1);}int maxfd=-1;fd_set rfds;char buffer[1025];int retval;struct timeval time;struct sockaddr_in addr;int len;bzero(&addr,sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(SER_PORT);addr.sin_addr.s_addr=inet_addr("127.0.0.1");connect(sockfd,(struct sockaddr *)&addr,sizeof(addr));while(1){FD_ZERO(&rfds);FD_SET(0,&rfds);maxfd=0;FD_SET(sockfd,&rfds);if(sockfd>maxfd){maxfd=sockfd;}time.tv_sec=1;time.tv_usec=0;retval=select(maxfd+1,&rfds,NULL,NULL,&time);if(retval==-1){perror("select error");break;}else if(retval==0){continue;}else{if(FD_ISSET(sockfd,&rfds)){bzero(buffer,1025);len=recv(sockfd,buffer,1024,0);if(len>0){cout<<buffer<<endl;}else{if(len<0){perror("recv error");}break;}}if(FD_ISSET(0,&rfds)){bzero(buffer,1025);fgets(buffer,1024,stdin);len=send(sockfd,buffer,strlen(buffer)-1,0);if(len<0){perror("send error");}}}}close(sockfd);return 0;}

完事。。。

如果觉得《Linux ubuntu18.04下socket聊天室 私聊 群聊》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。