这个聊天室写出来也有一段时间了
先来几张效果图
进入界面

登录成功界面

群聊时三个客户端界面
群聊时服务器打印信息

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

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

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

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

还有就是mysql 的简单操作

  1. create database 数据库名 ------新建数据库
  2. show create database ------查看数据库定义
  3. drop database 数据库名 ------删除数据库
  4. use 数据库名 ------操作对象切换
  5. 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 12345
struct 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 12345
int 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聊天室 私聊 群聊相关推荐

  1. socket聊天室实现-群聊,私聊,好友列表,完整版

    效果图 登录.好友上线,下线均提示. 点击好友列表所有人,发送消息,既为群聊 点击好友列表,好友名字,既为选中此好友进行私聊 服务器端代码 ChatRoomServer package sram.se ...

  2. ubuntu18.04下hadoop安装与集群配置

    ubuntu18.04下hadoop安装与集群配置 hadoop安装_单机/伪分布式配置 环境 创建hadoop用户 更新apt 安装SSH.配置SSH无密码登陆 安装Java环境 安装 Hadoop ...

  3. springboot+websocket构建在线聊天室(群聊+单聊)

    系列导读: 1.springboot+websocket构建在线聊天室(群聊+单聊) 2.Spring Boot WebSocket:单聊(实现思路) 3.Websocket Stomp+Rabbit ...

  4. 【uni-app】小程序实现微信在线聊天(私聊/群聊)

    之前学习使用uni-app简单实现一个在线聊天的功能,今天记录一下项目核心功能的实现过程.页面UI以及功能逻辑全部来源于微信,即时聊天业务的实现使用socket.io,前端使用uni-app开发,后端 ...

  5. django+vue3实现websocket聊天室(群聊)

    1.如何实现聊天功能 2.什么是websocket 2.1解释什么叫全双工,半双工,单工 3.websocker的概念 4.websocket的优点 5.django ,vue如何实现websocke ...

  6. Node + WebSocket + Vue 聊天室创建群聊/加入群聊功能 – 第五章

    前言 本次算是做了一个小小的专题吧,"Nodejs + WebSocket + Vue实现聊天室功能",目前还在一步一步推进,之前已经可以一对一.一对多聊天了,今天就来创建群聊组, ...

  7. Go实现简易聊天室(群聊)

    参考:Go 群聊 ( goroutine ) · 语雀 基于websocket的聊天室,可进一步参考: (1) go实现聊天室(WebSocket方式) (2) Golang代码搜集-基于websoc ...

  8. 佳信客服接口文档 REST API(第二部分)包含用户、聊天室、群聊、消息管理,通用接口数据结构、通用接口返回码

    6.聊天室管理 6.1.添加聊天室 接口定义: 请求URI https://api.jiaxincloud.com/rest/{orgName}/{appName}/chatrooms 访问角色 de ...

  9. C++ 实现聊天室(群聊、单聊、文件传送)

    文章目录 前言 一.前置知识点 1.相关文章 2.WTL的基本使用流程 二.项目下载与文件介绍 三.服务器代码讲解 1.NetPacket类 2.dealCli函数 3.NoticeOtherUser ...

  10. SpringBoot+STOMP 实现聊天室(单聊+多聊)及群发消息详解

    上篇系列文章:springboot+websocket构建在线聊天室(群聊+单聊) 最近发现stomp协议来实现长连接,非常简单(springboot封装的比较好) 本系列文章: 1.springbo ...

最新文章

  1. 同一个字符串hash值相同吗_图说:为什么Java中的字符串被定义为不可变的
  2. 5G 承载网 — 前传、中传、回传
  3. eclipse和jdk的版本问题,比如printf()出错
  4. Kaggle竞赛宝典方案汇总
  5. 「Python」conda与pip升级所有的包
  6. 【Oracle】闪回表
  7. wordpress之插件安装和主题安装(包含常见问题)
  8. linux的文件系统简单介绍
  9. 2021-07-13
  10. 关于华为手机无线调试
  11. springboot 设置全局字符编码,解决乱码问题
  12. 卢亮/明珠的博客吧开张了……
  13. 【GPL和LGPL】【VPlayer不开源】【其他开源的基本都仅是ffmpeg修改部分】
  14. linux memery dump
  15. 我的世界服务器怎么做无限的弓,我的世界制作无限弓流程介绍
  16. RocketMQ消息发送源码解析
  17. sendgrid_电子邮件即服务第2部分:Sendgrid,Mailgun和邮戳
  18. LOAM论文和程序代码的解读
  19. 独立游戏资源宝库,Unity AssetStore上最受欢迎的免费资源
  20. JAVA信息管理系统毕业设计 开题报告

热门文章

  1. python凯撒密码实验报告_凯撒密码的python实现
  2. 随机预言机模型 Random Oracle Model
  3. MICCAI 2022 | 深圳大学医学部智能超声实验室6篇论文分享!
  4. Points、inches和EMUs:Office Open XML中的度量单位
  5. python 方差_python 方差_python 方差齐性检验_方差 python - 云+社区 - 腾讯云
  6. 鸿蒙系统是不是无法注册gmail邮箱也无法正常使用youtube?
  7. Mstar 平台背光时序调试
  8. 根据26字母排列来搜索排列全国城市
  9. 职称论文发表格式要求
  10. SpringBoot 整合ActiveMQ