用TCP实现简易版聊天室
TCP相较于UDP和select有着传输稳定的优点。
介于之前用select已经实现过,所以本程序只有注册,登录,忘记密码,私聊,群聊,注销,退出等功能
当然,tcp也是可以实现之前能用select实现的所有功能。
废话不多说,上代码:
头文件
#ifndef _CHAT_H_
#define _CHAT_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORT 8888
#define FAILURE 10000
#define SUCCESS 10001
#define ERROR1 10002
#define ERROR2 10003
#define RIGHT 10004
#define SIGN 1 //注册
#define LOGO 2 //登陆
#define FORGET 3 //忘记密码
#define QUIT 4 //退出
#define SHOW 5 //显示用户
#define PCHAT 6 //私聊
#define GCHAT 7 //群聊
#define BACK 8 //注销
#define CQUIT 9 //客户端退出
#define SHOWNUM 10 //显示在线人数
struct communication
{
int idnumber; //帐号
char password[20]; //密码
int sex; //性别 0 m 1 f
char telephone[20]; //手机号
char nickname[20]; //昵称
int time_sr; //收发消息时间
char message[100]; //消息
int num; //在线人数
char Fromnickname[20]; //发消息人的昵称
int ToFd; //目的地 0表示和服务器通信
int flag; //宏标志
int endflag; //结束标志位
};
typedef struct communication commu;
struct status
{
int idnumber; //帐号
char nickname[20]; //昵称
int usersockfd; //用户fd
struct status *next;
};
typedef struct status Status;
typedef Status * STATUS;
/*********************************************服务器***********************************/
void *server_receive(void *arg);
void server_sign(commu RecvBuf, int aim);
int compare(void *para, int columnCount, char **columnValue, char **columnName);
void server_logo(commu RecvBuf, int aim);
int compare1(void *para, int columnCount, char **columnValue, char **columnName);
void server_forget(commu RecvBuf, int aim);
void server_show(commu RecvBuf, int aim);
void server_pchat(commu RecvBuf, int aim);
void server_gchat(commu RecvBuf, int aim);
/*********************************************客户端***********************************/
void show_welcome();
void show_sign();
void sign_in(int sockfd);
void show_logo();
void logo_in(int sockfd);
void show_forget();
void forget_password(int sockfd);
void client_quit(int sockfd);
void show_in();
void show_quit();
void delay();
void show_menu();
void *client_menu(void *arg);
void private_chat(void *arg);
void show_people(int sockfd);
void *Send(void *arg);
void *Recv(void *arg);
void group_chat(int sockfd);
void client_back(int sockfd);
void client_cquit();
#endif
服务器
#include "chat.c"
sqlite3 *ppdb;
STATUS sta;
char sql[200] = {0};
int main()
{
int fd[100] = {0};
/*********************************************初始化用户链表***************************************/
sta = (STATUS)malloc(sizeof(Status));
sta->next = NULL;
/***********************************************打开数据库*************************************/
int ret;
ret = sqlite3_open("infor.db", &ppdb);
if(ret != SQLITE_OK)
{
perror("sqlite3_open");
exit(1);
}
sprintf(sql, "create table if not exists infor (idnumber integer primary key, password text, nickname text, sex interger, telephone text);");
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if(ret != SQLITE_OK)
{
perror("sqlite3_exec");
exit(1);
}
/************************************************线程通信************************************************/
int length, i = 0;
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
pthread_t tid[100] = {0};
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("bind");
exit(1);
}
printf("等待链接...\n");
ret = listen(sockfd, 20);
if(-1 == ret)
{
perror("listen");
exit(1);
}
while(1)
{
length = sizeof(client_addr);
fd[i] = accept(sockfd, (struct sockaddr*)&client_addr, &length);
if(-1 == fd[i])
{
perror("accept");
exit(1);
}
printf("第%d号用户,端口号:%d\n", fd[i], client_addr.sin_port);
ret = pthread_create(&tid[i], NULL, server_receive, (void *)&fd[i]);
if(0 != ret)
{
perror("pthread_create");
exit(1);
}
i++;
}
close(sockfd);
return 0;
}
客户端
#include "chat.c"
int fflag = 0; //跳出登录界面
pthread_t tid[2] = {0};
int main()
{
fflag = 0;
/*********************************************链接服务器***************************************/
int sockfd, ret;
struct sockaddr_in server_addr;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("正在连接服务器...\n");
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("connect");
exit(1);
}
/**********************************************登录界面选择********************************************/
char choice[10] = {0};
while(1)
{
// system("clear");
show_welcome();
scanf("%s", choice);
switch (atoi(&choice[0]))
{
case 1:
logo_in(sockfd);
if(fflag == 1)
{
show_in();
// sleep(2);
ret = pthread_create(&tid[0], NULL, client_menu, (void *)&sockfd);
if(0 != ret)
{
perror("pthread_create1");
exit(1);
}
ret = pthread_create(&tid[1], NULL, Recv, (void *)&sockfd);
if(0 != ret)
{
perror("pthread_create2");
exit(1);
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
}
break;
case 2:
sign_in(sockfd);
break;
case 3:
forget_password(sockfd);
break;
case 4:
client_quit(sockfd);
break;
default:
printf("请重输:\n");
break;
}
if(fflag == 2)
{
show_quit();
return 0;
}
}
return 0;
}
服务器接口
#include "chat.c"
extern sqlite3 *ppdb;
extern STATUS sta;
extern char sql[200];
int aim_a = 0;
int count = 0;
char name[20];
/***********************************************注册用户,写入数据库中********************************************/
void server_sign(commu RecvBuf, int aim)
{
printf("第%d号用户:注册!\n", aim); //
int ret;
aim_a = aim;
memset(&sql, 0, sizeof(sql)); //注意要取地址
sprintf(sql, "insert into infor (idnumber, password, nickname, sex, telephone) values (%d, '%s', '%s', %d, '%s');", RecvBuf.idnumber, RecvBuf.password, RecvBuf.nickname, RecvBuf.sex, RecvBuf.telephone);
// printf("id:%d passwd:%s nickname:%s sex:%d telephone:%s\n", RecvBuf.idnumber, RecvBuf.password, RecvBuf.nickname, RecvBuf.sex, RecvBuf.telephone); //
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if(ret != SQLITE_OK)
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = ERROR1;
// printf("flag4:%d\n", RecvBuf.flag); //
ret = send(aim, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
else
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = RIGHT;
// printf("flag5:%d\n", RecvBuf.flag); //
ret = send(aim, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
}
/**********************************************登录用户,登录成功加入链表中****************************************/
void server_logo(commu RecvBuf, int aim)
{
commu SendBuf;
count = 0;
printf("第%d号用户:登录!\n", aim); //
printf("id:%d passwd:%s\n", RecvBuf.idnumber, RecvBuf.password); //
int ret;
aim_a = aim;
memset(&sql, 0, sizeof(sql));
sprintf(sql ,"select * from infor;");
ret = sqlite3_exec(ppdb, sql, compare, (void *)&RecvBuf, NULL);
if(ret != SQLITE_OK)
{
perror("sqlite3_exec");
exit(1);
}
if(1 == count)
{
STATUS tmp = sta;
STATUS p = sta->next;
while(p)
{
if(p->idnumber == RecvBuf.idnumber)
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = FAILURE; //用户已在线
ret = send(aim, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
tmp = p;
p = p->next;
}
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = RIGHT; //登录成功
ret = send(aim, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
STATUS n = (STATUS)malloc(sizeof(Status));
if(NULL == n)
{
perror("malloc");
exit;
}
n->idnumber = RecvBuf.idnumber;
strcpy(n->nickname, name);
n->usersockfd = aim;
tmp->next = n;
n->next = NULL;
return;
}
else if(2 == count)
{
return;
}
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = ERROR1; //数据库空,用户没注册
ret = send(aim, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
int compare(void *para, int columnCount, char **columnValue, char **columnName)
{
commu RecvBuf;
int ret;
int j;
for(j = 0; j < columnCount; j++)
{
if((*(((int **)columnValue)[0]) - 48) == ((*(commu *)para).idnumber))
{
if(!strcmp(columnValue[1], ((*(commu *)para).password)))
{
memset(name, 0, sizeof(name));
strcpy(name, columnValue[2]);
count = 1;
return 0;
}
else
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = ERROR2; //帐号密码错误
ret = send(aim_a, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
count = 2;
return 0;
}
}
}
return 0;
}
/********************************************忘记密码****************************************************/
void server_forget(commu RecvBuf, int aim)
{
printf("第%d号用户:找回密码!\n", aim);
printf("id:%d, nickname:%s, sex:%d, telephone:%s\n", RecvBuf.idnumber, RecvBuf.nickname, RecvBuf.sex, RecvBuf.telephone);
count = 0;
commu SendBuf;
int ret;
aim_a = aim;
memset(&sql, 0, sizeof(sql));
sprintf(sql ,"select * from infor;");
ret = sqlite3_exec(ppdb, sql, compare1, (void *)&RecvBuf, NULL);
if(ret != SQLITE_OK)
{
perror("sqlite3_exec");
exit(1);
}
if(3 == count)
{
return;
}
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = ERROR1; //没有该用户,返回错误
ret = send(aim, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
int compare1(void *para, int columnCount, char **columnValue, char **columnName)
{
commu RecvBuf;
commu SendBuf;
int ret;
int j;
char pswd[20];
for(j = 0; j < columnCount; j++)
{
memset(pswd, 0, sizeof(pswd));
strcpy(pswd, columnValue[1]);
printf("pswd:%s\n", pswd);
printf("columnValue[1]:%s\n", columnValue[1]);
if(((*(columnValue[0]) - 48) == (*(commu *)para).idnumber) && (!strcmp(columnValue[2], ((*(commu *)para).nickname))) && ((*(columnValue[3]) - 48) == (*(commu *)para).sex) && (!strcmp(columnValue[4], ((*(commu *)para).telephone))))
{
STATUS p = sta->next;
while(p)
{
if(p->idnumber == (*(commu *)para).idnumber)
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
RecvBuf.flag = FAILURE; //用户已在线,返回失败
ret = send(aim_a, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
count = 3;
return 0;
}
p = p->next;
}
printf("jinglema?\n");
memset(&SendBuf, 0, sizeof(SendBuf)); //用户不在线,返回正确
SendBuf.flag = RIGHT;
strcpy(SendBuf.password, pswd);
printf("sf1:%d\n",SendBuf.flag);
printf("Sendpswd:%s\n", SendBuf.password);
ret = send(aim_a, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
count = 3;
return 0;
}
}
return 0;
}
/********************************************显示当前在线人数*********************************************/
void server_show(commu RecvBuf, int aim)
{
commu SendBuf;
int ret, i = 0, j = 0;
STATUS p = sta->next;
while(p)
{
i++;
p = p->next;
}
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.num = i;
SendBuf.flag = SHOWNUM;
ret = send(aim, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
p = sta->next;
for(j; j < i-1; j++)
{
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = SHOW;
strcpy(SendBuf.nickname, p->nickname);
ret = send(aim, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
p = p->next;
}
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = SHOW;
SendBuf.endflag = 1;
strcpy(SendBuf.nickname, p->nickname);
ret = send(aim,&SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
p = p->next;
return;
}
/********************************************私聊*********************************************************/
void server_pchat(commu RecvBuf, int aim)
{
int ret;
aim_a = 0;
STATUS p;
p = sta->next;
while(p)
{
if(!strcmp(RecvBuf.nickname, p->nickname))
{
aim_a = p->usersockfd;
}
p = p->next;
}
p = sta->next;
if(0 == aim_a)
{
commu SendBuf;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = FAILURE;
strcpy(SendBuf.nickname, RecvBuf.nickname);
ret = send(aim , &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
}
else
{
while(p)
{
if(p->usersockfd == aim)
{
strcpy(RecvBuf.Fromnickname, p->nickname);
ret = send(aim_a, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
}
p = p->next;
}
}
return;
}
/*********************************************群发********************************************************/
void server_gchat(commu RecvBuf, int aim)
{
aim_a = 0;
int ret;
STATUS p;
p = sta->next;
while(p)
{
if(aim == p->usersockfd)
{
strcpy(RecvBuf.Fromnickname, p->nickname);
}
p = p->next;
}
p = sta->next;
while(p)
{
if(aim != p->usersockfd)
{
aim_a = p->usersockfd;
ret = send(aim_a, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
}
p = p->next;
}
if(0 == aim_a)
{
commu SendBuf;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = ERROR1;
ret = send(aim, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
}
return;
}
/*************************************************注销****************************************************/
void server_back(commu RecvBuf, int aim)
{
int ret;
STATUS tmp = sta;
STATUS p = sta->next;
while(p)
{
if(aim == p->usersockfd)
{
if(p->next == NULL)
{
tmp->next = NULL;
free(p);
}
else
{
tmp->next = p->next;
free(p);
p->next = NULL;
}
}
tmp = p;
p = p->next;
}
return;
}
/****************************************************CQUIT************************************************/
void server_cquit(commu RecvBuf, int aim)
{
int ret;
STATUS tmp = sta;
STATUS p = sta->next;
while(p)
{
if(aim == p->usersockfd)
{
if(p->next == NULL)
{
tmp->next = NULL;
free(p);
}
else
{
tmp->next = p->next;
free(p);
p->next = NULL;
}
}
tmp = p;
p = p->next;
}
return;
}
/********************************************服务器依据flag处理客户端消息*********************************/
void *server_receive(void *arg)
{
commu RecvBuf;
int ret, ffflag = 0;
pthread_detach(pthread_self());
while(1)
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
ret = recv(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
printf("flag3:%d\n", RecvBuf.flag); //
printf("id:%d passwd:%s\n", RecvBuf.idnumber, RecvBuf.password); //
switch (RecvBuf.flag)
{
case LOGO:
server_logo(RecvBuf, *(int *)arg);
break;
case SIGN:
server_sign(RecvBuf, *(int *)arg);
break;
case FORGET:
server_forget(RecvBuf, *(int *)arg);
break;
case QUIT:
ffflag = 1;
break;
case SHOW:
server_show(RecvBuf, *(int *)arg);
break;
case PCHAT:
server_pchat(RecvBuf, *(int *)arg);
break;
case GCHAT:
server_gchat(RecvBuf, *(int *)arg);
break;
case BACK:
server_back(RecvBuf, *(int *)arg);
break;
case CQUIT:
server_cquit(RecvBuf, *(int *)arg);
ffflag = 1;
break;
default:
break;
}
if(ffflag == 1)
{
break;
}
}
if(ffflag == 1)
{
printf("第%d用户,退出!\n", *(int *)arg);
close(*(int *)arg);
}
}
客户端接口
#include "chat.c"
extern int fflag; //跳出登录界面
extern pthread_t tid[2];
void show_welcome()
{
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t\t欢迎来到聊天室!\n");
printf("\t\t\t\t\t\t WELCOME TO CHAT ROOM!\n");
printf("\n\n\n\n");
printf("\t\t\t\t1.登录帐号\n");
printf("\n");
printf("\t\t\t\t2.注册帐号\n");
printf("\n");
printf("\t\t\t\t3.忘记密码\n");
printf("\n");
printf("\t\t\t\t4.退出\n");
printf("\n\n\n\n\n\n");
}
/********************************************************用户注册**********************************************/
void show_sign()
{
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t请输入帐号:\n");
printf("\n");
printf("\t\t\t\t请输入密码:\n");
printf("\n");
printf("\t\t\t\t请输入昵称:\n");
printf("\n");
printf("\t\t\t\t帅哥输入0,美女输入1:\n");
printf("\n");
printf("\t\t\t\t请输入手机号:\n");
printf("\n\n\n\n\n\n\n");
}
void sign_in(int sockfd)
{
// system("clear");
show_sign();
int ret;
int userid;
char userpassword[20];
char usernickname[20];
int usersex;
char usertelephone[20];
scanf("%d %s %s %d %s", &userid, userpassword, usernickname, &usersex, usertelephone);
commu userinfor;
memset(&userinfor, 0, sizeof(userinfor));
userinfor.idnumber = userid;
strcpy(userinfor.password, userpassword);
strcpy(userinfor.nickname, usernickname);
userinfor.sex = usersex;
strcpy(userinfor.telephone, usertelephone);
userinfor.flag = SIGN;
// printf("%d %s %s %d %s\n", userid, userpassword, usernickname, usersex, usertelephone);
// printf("flag1:%d\n", userinfor.flag);
ret = send(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
memset(&userinfor, 0, sizeof(userinfor));
ret = recv(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
// printf("flag2:%d\n", userinfor.flag);
if(userinfor.flag == ERROR1)
{
printf("注册失败,账户已存在!\n");
}
else if(userinfor.flag == RIGHT)
{
printf("注册成功!\n");
}
return;
}
/************************************************用户登录************************************************/
void show_logo()
{
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t请输入帐号:\n");
printf("\n");
printf("\t\t\t\t请输入密码:\n");
printf("\n\n\n\n\n\n");
}
void logo_in(int sockfd)
{
int userid, ret;
char userpassword[20];
// system("clear");
show_logo();
commu userinfor;
memset(&userinfor, 0, sizeof(userinfor));
scanf("%d %s", &userinfor.idnumber, userinfor.password);
userinfor.flag = LOGO;
ret = send(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
memset(&userinfor, 0, sizeof(userinfor));
ret = recv(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
if(userinfor.flag == ERROR1)
{
printf("登录失败,该用户未注册!\n");
}
else if(userinfor.flag == FAILURE)
{
printf("登录失败,该用户已在线!\n");
}
else if(userinfor.flag == ERROR2)
{
printf("登录失败,帐号密码错误!\n");
}
else
{
printf("登录成功!\n");
fflag = 1;
}
return;
}
/**************************************************忘记密码*****************************************/
void show_forget()
{
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t\t请输入以下注册时输入的信息\n");
printf("\n\n\n\n");
printf("\t\t\t\t请输入帐号:\n");
printf("\n");
printf("\t\t\t\t请输入昵称:\n");
printf("\n");
printf("\t\t\t\t请输入性别:\n");
printf("\n");
printf("\t\t\t\t请输入手机号:\n");
printf("\n\n\n\n");
printf("\t\t\t\t请输入您的选择:\n");
printf("\n\n");
}
void forget_password(int sockfd)
{
int userid, ret;
char usernickname[20];
int usersex;
char usertelephone[20];
// system("clear");
show_forget();
scanf("%d %s %d %s", &userid, usernickname, &usersex, usertelephone);
commu userinfor;
memset(&userinfor, 0, sizeof(userinfor));
userinfor.idnumber = userid;
strcpy(userinfor.nickname, usernickname);
userinfor.sex = usersex;
strcpy(userinfor.telephone, usertelephone);
userinfor.flag = FORGET;
ret = send(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
memset(&userinfor, 0, sizeof(userinfor));
ret = recv(sockfd, &userinfor, sizeof(userinfor), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
if(userinfor.flag == ERROR1)
{
printf("该用户不存在!\n");
}
else if(userinfor.flag == FAILURE)
{
printf("该用户已在线!\n");
}
else if(userinfor.flag == RIGHT)
{
printf("帐号密码是:%s\n", userinfor.password);
}
return;
}
/*************************************************登录界面退出******************************************/
void client_quit(int sockfd)
{
commu SendBuf;
int ret;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = QUIT;
ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
close(sockfd);
fflag = 2;
return;
}
/***************************************************跳转界面******************************************/
void show_in()
{
// system("clear");
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t\t欢迎进入聊天室!\n");
printf("\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t\t\t\t\t\t正在连接服务器...\n");
printf("\n\n\n\n\n\n");
}
/***************************************************退出界面****************************************/
void show_quit()
{
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t正在退出...\n");
// sleep(2);
// system(clear");
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t\t再见!\n");
printf("\n");
printf("\t\t\t\t\t\t\tGOOD BYE\n");
printf("\n\n\n\n\n\n\n");
// system("clear");
return;
}
/***************************************************主菜单*****************************************/
void show_menu()
{
printf("\n\n");
printf("\t\t\t\t\t\t\t\t主菜单\n");
printf("\n\n\n");
printf("\t\t\t\t1 . 私聊\n");
printf("\n");
printf("\t\t\t\t2 . 群聊\n");
printf("\n");
printf("\t\t\t\t3 . 注销\n");
printf("\n");
printf("\t\t\t\t4 . 退出\n");
printf("\n");
printf("\t\t\t\t5 . 刷新\n");
printf("\n\n\n");
printf("\t\t\t\t请输入您的选择:\n");
}
void *client_menu(void *arg)
{
int jihao = 0;
char choice[10] = {0};
// system("clear");
while(1)
{
show_menu();
printf("\n\n");
show_people(*(int *)arg);
scanf("%s", choice);
switch (atoi(&choice[0]))
{
case 1:
private_chat(arg);
break;
case 2:
group_chat(*(int *)arg);
break;
case 3:
client_back(*(int *)arg);
jihao = 1;
break;
case 4:
client_cquit(*(int *)arg);
jihao = 1;
break;
default:
break;
}
if(1 == jihao)
{
pthread_cancel(tid[1]);
return;
}
}
}
/**********************************************接受消息********************************************/
void *Recv(void *arg)
{
static cendflag = 0;
int ret, oldtype;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
commu RecvBuf;
while(1)
{
memset(&RecvBuf, 0, sizeof(RecvBuf));
ret = recv(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0);
if(-1 == ret)
{
perror("Recv");
exit(1);
}
// printf("recvbuf:%d\n", RecvBuf.flag);
if(RecvBuf.flag == FAILURE)
{
printf("\n\n");
printf("发送失败,用户%s不在线!\n", RecvBuf.nickname);
printf("\n\n");
}
else if(RecvBuf.flag == ERROR1)
{
printf("\n\n");
printf("消息发送失败,当前用户只有您一个人在线!\n");
printf("\n\n");
}
else if(RecvBuf.flag == SHOWNUM)
{
printf("\n\n");
printf("当前在线人数:%d\n", RecvBuf.num);
printf("\n\n");
}
else if(RecvBuf.flag == SHOW)
{
if(RecvBuf.endflag == 0)
{
printf("\t\t%d. %s\n", cendflag + 1, RecvBuf.nickname);
cendflag++;
}
else if(RecvBuf.endflag == 1)
{
printf("\t\t%d. %s\n", cendflag + 1, RecvBuf.nickname);
cendflag = 0;
printf("\n\n");
}
}
else if(RecvBuf.flag == GCHAT)
{
printf("\n\n");
printf("您有新的群消息:\n");
printf("\t\t\t\t%s对您说:%s\n", RecvBuf.Fromnickname, RecvBuf.message);
printf("\n\n");
}
else if(RecvBuf.flag == PCHAT)
{
printf("\n\n");
printf("您有新消息:\n");
printf("\t\t\t\t%s对您说:%s\n", RecvBuf.Fromnickname, RecvBuf.message);
printf("\n\n");
}
}
return;
}
/***********************************************显示在线人数*****************************************/
void show_people(int sockfd)
{
int ret, j = 0, i = 0;
commu SendBuf;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = SHOW;
ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
/*************************************************私聊*********************************************/
void private_chat(void *arg)
{
int ret, oldtype;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
while(1)
{
printf("\t\t\t\t请输入私聊对象的昵称:\n");
printf("\n");
printf("\t\t\t\t请输入私聊内容:\n");
char cnickname[20] = {0};
char cmessage[100] = {0};
scanf("%s %s", cnickname, cmessage);
commu SendBuf;
memset(&SendBuf, 0, sizeof(SendBuf));
strcpy(SendBuf.nickname, cnickname);
strcpy(SendBuf.message, cmessage);
SendBuf.flag = PCHAT;
ret = send(*(int *)arg, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
if(!strcmp(SendBuf.message, "#end"))
{
break;
}
return;
}
return;
}
/************************************************群聊*********************************************/
void group_chat(int sockfd)
{
int ret;
commu SendBuf;
printf("请输入想要发送的消息:\n");
scanf("%s", SendBuf.message);
SendBuf.flag = GCHAT;
ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
/****************************************客户端menu回主界面(注销)**********************************/
void client_back(int sockfd)
{
commu SendBuf;
int ret;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = BACK;
ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
return;
}
/**********************************************客户端退出*****************************************/
void client_cquit(int sockfd)
{
commu SendBuf;
int ret;
memset(&SendBuf, 0, sizeof(SendBuf));
SendBuf.flag = CQUIT;
ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
if(-1 == ret)
{
perror("send");
exit(1);
}
pthread_cancel(tid[1]);
client_quit(sockfd);
fflag = 2;
return;
}