这个聊天室完成了一些基础功能私聊、群聊、文件传送等基础功能,可以添加表情符号等其他功能。
头文件中的名称的定义可以换成枚举形式,会更加方便一点,我脑抽了就不改了。有空再完善代码规范和功能。
myhead.h
#ifndef _MYHEAD_H_
#define _MYHEAD_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFSIZE 50
#define MYPORT 6656
#define MYADDR "192.168.1.200"
/**功能选择**/
#define REG 1
#define LOGIN 2
#define PRIVATE_CHAT 3
#define GROUP_CHAT 4
#define VIEW_FRIENDS 5
#define CORRECT_PIN_NUMBER 6
#define ADMINI_PRIVILEGE 7
#define SEND_OFFLINE_MSG 8
#define SEND_FILE 9
#define SIGN 10
#define OFF_LINE 11
#define VIEW_USER_MSG 26
#define BECOME_VIP 39 //成为VIP
/**登陆注册**/
#define REG_SUCCESS 12
#define REG_FAIL 13
#define LOGIN_SUCCESS 14
#define LOGIN_FAIL 15
#define LOGIN_EXIT 16
/**创建链表**/
#define CREATE_NODE 17
/************/
#define PRIVATE_SUCCESS 18
#define PRIVATE_FAIL 19
#define GROUP_SUCCESS 20
#define VIEW_FRIENDS_SUCCESS 21
#define CORRECT_SUCCESS 22
#define CORRECT_FAIL 23
#define CORRECT_OLD 24 //用户原密码输入错误
#define OFF_LINE_SUCCESS 27
#define OFF_LINE_FAIL 28
/**权限**/
#define BAN 29 //禁言
#define REMOVE 30 //解禁
#define KICK 31 //踢人
#define BAN_USER 32 //返回给被禁言的用户
#define REMOVE_USER 33 //返回给被解禁的用户
#define KICK_FAIL 34
#define BEEN_KICK 35
#define NO_POWER 36 //没有vip权限
#define SIGN_SUCCESS 37
#define SEND_SUCCESS 38 //发送离线消息成功
#define VIP_SUCCESS 42
//#define BECOME_VIP 39 //成为VIP
#define SHOW_INFO 43
/**文件**/
#define FILE_SUCCESS 40
#define FILE_FAIL 41
typedef struct users //用户信息:链表
{
//struct regist *user;
char username[20]; //用户名
int clientfd;
int power; //1:禁言,0:未禁言
struct users *next;
}user;
typedef struct regist //注册
{
int flag; //注册登录标志符
int vip; //会员用户 为1时具有会员权限,为0没有
char username[20]; //用户名
char password[20]; //密码
char new_passwd1[20]; //新密码
char new_passwd2[20]; //新密码验证
char file[1024]; //文件
char filename[20]; //文件名
char sign[50]; //个性签名
// int friend_num; //好友数
// int group_num; //群组数
char offline_msg[500]; //离线消息
int action; //通过action表明是什么命令;
char fromname[20];
char toname[20];
char time[20]; //时间
char msg[500]; //消息内容
}client;
char my_getch()
{
char temp = 0;
temp = getchar();
}
#endif
#include "myhead.h"//server
void *read_msg_server(void *argc);
void register_client(int clientfd);
void login_client(int clientfd);
void private_chat(int clientfd);
sqlite3 *db = NULL;
char *errmsg = NULL;
char **result = NULL;
char sql[1024] = {0};
struct users *head = NULL; //创建用户信息的头结点
user userbuff;
client clientrecv;
int main()
{
int socketfd = 0;
int clientfd = 0;
int ret = 0;
struct sockaddr_in server_addr = {0};
struct sockaddr_in client_addr = {0};
socklen_t len = sizeof(struct sockaddr);
pthread_t th;
char recvbuff[20] = {0};
int recvcnt = 0;
char sendbuff[20] = {0};
int sendcnt = 0;
head = (struct users*)malloc(sizeof(struct users));
if(head == NULL)
{
printf("malloc error\n");
}
//head->next = NULL;
ret = sqlite3_open("chat.db",&db); //建数据库
if(ret != SQLITE_OK)
{
printf("数据库打开失败!");
}
sqlite3_exec(db,"create table account(username text primary key,password text,vip INTEGER,sign text,offline_msg text);",NULL,NULL,&errmsg); //建注册信息表
socketfd = socket(AF_INET,SOCK_STREAM,0); //1.调用socket创建套接字
if(socketfd == -1)
{
perror("socket");
return -1;
}
printf("socket success...\n");
bzero(&server_addr,sizeof(server_addr)); //2.绑定:==》地址族,端口号,IP地址;下面就是赋值操作!
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MYPORT);
server_addr.sin_addr.s_addr = inet_addr(MYADDR);
ret = bind(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
if(ret == -1)
{
perror("bind");
return -1;
}
printf("bind success...\n");
ret = listen(socketfd,10);
if(ret == -1)
{
perror("listen");
return -1;
}
printf("listen success...\n");
while(1)
{
clientfd = accept(socketfd,(struct sockaddr *)&client_addr,&len);
if(clientfd == -1)
{
perror("accept");
return -1;
}
printf("accept success... ");
if(pthread_create(&th,NULL,read_msg_server,&clientfd) == -1)
{
perror("pthread_create");
return -1;
}
pthread_detach(th);
}
// close(socketfd);
sqlite3_free_table(result);
slqite3_close(db);
return 0;
}
void *read_msg_server(void *argc)
{
struct users *p = head;
int clientfd = *((int *)argc);
printf("read_msg_server:clientfd = %d\n",clientfd);
int readcnt = 0;
int writecnt = 0;
while(1)
{
int login_flag = 0;
memset(&clientrecv,0,sizeof(client));
readcnt = read(clientfd,&clientrecv,sizeof(client));
if(readcnt == -1)
{
perror("read_msg_client:read");
return 0;
}
switch(clientrecv.action)
{
case 1: //注册
{
register_client(clientfd);
break;
}
case 2: //登录
{
//login_client(clientfd);
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.username,result[i*ncolumn]) == 0 && strcmp(clientrecv.password,result[i*ncolumn+ 1]) == 0)
{
flag = 1;
//strcpy(buff,clientrecv.username);
}
}
}
p = head;
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.username) == 0)
{
clientrecv.flag = LOGIN_EXIT; //该用户已登录
write(clientfd,&clientrecv,sizeof(client));
}
}
if(flag == 0) //登录失败
{
clientrecv.flag = LOGIN_FAIL;
write(clientfd,&clientrecv,sizeof(client));
}
else if(flag == 1) //登录成功
{
clientrecv.flag = LOGIN_SUCCESS;
write(clientfd,&clientrecv,sizeof(client));
struct users *new = (struct users *)malloc(sizeof(struct users));
strcpy(new->username,clientrecv.username);
new->clientfd = clientfd;
/*************************权限状态需要从数据库中读取**********************************/
new->power = 0; //未禁言状态
if(new == NULL)
{
printf("malloc error!\n");
//return NULL;
}
/* p = head;
while(p->next != NULL) //p不是尾结点
{
p = p->next;
}
*/p->next = new;
new->next = NULL;
//bzero(p,sizeof(struct users));
}
break;
}
case 3: //私聊
{
//private_chat(clientfd);
p = head;
int temp = 0;
while(p->next !=NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.toname) == 0) //存在该好友
{
temp = 1;
//clientfd = p->clientfd;
clientrecv.flag = PRIVATE_SUCCESS;
//printf("m\n");
printf("testing!!!\n");
printf("%s(%d)send to%s(%d)",clientrecv.fromname,clientfd,clientrecv.toname,p->clientfd);
write(p->clientfd,&clientrecv,sizeof(client)); //发送给好友
break;
}
}
if(temp == 0)
{
clientrecv.flag = PRIVATE_FAIL; //查无此人,回复给用户
write(clientfd,&clientrecv,sizeof(client));
}
break;
}
case 4: //群聊
{
p = head;
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.username) == 0)
{
if(p->power == 1)
{
//memset(&clientrecv,0,sizeof(client));
clientrecv.flag = NO_POWER; //无发送权限,已被禁言
writecnt = write(p->clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
}
else if(p->power == 0)
{
p = head;
while(p->next != NULL)
{
p = p->next;
// if(strcmp(p->username,clientrecv.username) != 0)
{
clientrecv.flag = PRIVATE_SUCCESS;
writecnt = write(p->clientfd,&clientrecv,sizeof(client)); //发送给群
if(writecnt == -1)
{
perror("group:write");
return 0;
}
}
}
printf("%s(%d)send :\n",clientrecv.fromname,clientfd);
}
break;
}
}
break;
}
case 5: //查看在线好友链表
{
p = head;
char buff[20] = {0};
strcpy(buff,clientrecv.username);
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,buff) != 0) //不显示自己的用户名,只显示好友列表
{
clientrecv.flag = VIEW_FRIENDS_SUCCESS;
strcpy(clientrecv.username,p->username);
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
}
}
break;
}
case 6: //修改密码
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int ret = 0;
int flag = 0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.password,result[i*ncolumn+ 1]) == 0)//&&clientrecv.username == result[i*ncolumn]
{
flag = 1;
}
}
}
if(flag == 1) //用户原密码输入正确时
{
if(strcmp(clientrecv.new_passwd1,clientrecv.new_passwd2) == 0) //新密码成功修改
{
sprintf(sql,"update account set password = '%s' where username = '%s';",clientrecv.new_passwd1,clientrecv.username);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(ret != SQLITE_OK) //数据库中修改失败
{
clientrecv.flag = CORRECT_FAIL;
write(clientfd,&clientrecv,sizeof(client));
}
else
{
clientrecv.flag = CORRECT_SUCCESS;
write(clientfd,&clientrecv,sizeof(client));
}
}
else //新密码修改失败
{
clientrecv.flag = CORRECT_FAIL;
write(clientfd,&clientrecv,sizeof(client));
}
}
else if(flag == 0) //用户原密码输入错误时
{
clientrecv.flag = CORRECT_OLD;
write(clientfd,&clientrecv,sizeof(client));
}
break;
}
case 8: //发送离线消息(私聊转离线)
{
int ret = 0;
p = head;
int temp = 0;
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.toname) == 0) //用户在线
{
temp = 1;
}
}
if(temp == 0)
{
sprintf(sql,"insert into account (offline_msg) values('%s') where username = '%s';",clientrecv.msg,clientrecv.toname);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg); //离线消息插入数据库
clientrecv.flag = SEND_SUCCESS;
write(clientfd,&clientrecv,sizeof(client));
}
break;
}
case 9: //发送文件
{
int ret = 0;
p = head;
int temp = 0;
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.toname) == 0)
{
temp = 1;
clientrecv.flag = FILE_SUCCESS;
printf("%s(%d)send to%s(%d)",clientrecv.fromname,clientfd,clientrecv.toname,p->clientfd);
write(p->clientfd,&clientrecv,sizeof(client)); //发送给好友
break;
}
}
if(temp = 0)
{
clientrecv.flag = FILE_FAIL; //查无此人
write(clientfd,&clientrecv,sizeof(client));
}
}
case 10: //修改个性签名
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int ret = 0;
int flag = 0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
{
sprintf(sql,"update account set sign = '%s' where username = '%s';",clientrecv.sign,clientrecv.username);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(ret != SQLITE_OK) //修改失败
{
return 0; //修改个签失败处理
}
clientrecv.flag = SIGN_SUCCESS;
}
}
}
write(clientfd,&clientrecv,sizeof(client));
break;
}
case 11: //下线
{
p = head;
struct users *prev = NULL;
while(p->next != NULL)
{
prev = p; //prev保存p点前一个结点的地址
p = p->next;
if(strcmp(p->username,clientrecv.username) == 0) //找到该用户
{
if(p->next == NULL) //尾结点
{
prev->next = NULL;
free(p);
//p = NULL; //NULL->next != NULL 出现段错误
clientrecv.flag = OFF_LINE_SUCCESS;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
else
{
prev->next = p->next;
free(p);
//p = NULL;
clientrecv.flag = OFF_LINE_SUCCESS;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
}
}
clientrecv.flag = OFF_LINE_FAIL; //下线失败
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
case 29: //禁言
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
int temp = 0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //无vip权限
{
clientrecv.flag = NO_POWER; //无权限
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //有vip权限
{
flag = 1;
}
}
}
if(flag == 1) //有禁言权限
{
p = head;
while(p->next != NULL)
{
p = p->next;
if(strcmp(clientrecv.toname,p->username) == 0)
{
p->power = 1;
clientrecv.flag = BAN;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
clientrecv.flag = BAN_USER;
writecnt = write(p->clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
}
}
break;
}
case 30: //解禁
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //无vip权限
{
clientrecv.flag = NO_POWER; //无权限
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
}
else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //有vip权限
{
flag = 1;
}
}
}
if(flag == 1)
{
p = head;
while(p->next != NULL)
{
p = p->next;
if(strcmp(clientrecv.toname,p->username) == 0)
{
p->power = 0;
clientrecv.flag = REMOVE;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
clientrecv.flag = REMOVE_USER;
writecnt = write(p->clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
}
}
break;
}
case 31: //踢人
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(atoi(result[i*ncolumn + 2]) == 0 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //无vip权限
{
clientrecv.flag = NO_POWER; //无权限
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
}
else if(atoi(result[i*ncolumn + 2]) == 1 && strcmp(clientrecv.username,result[i*ncolumn]) == 0) //有vip权限
{
flag = 1;
}
}
}
if(flag == 1)
{
p = head;
struct users *prev = NULL;
while(p->next != NULL)
{
prev = p; //prev保存p点前一个结点的地址
p = p->next;
if(strcmp(p->username,clientrecv.toname) == 0)
{
if(p->next == NULL) //尾结点
{
prev->next = NULL;
free(p);
//p = NULL; //NULL->next != NULL 出现段错误
clientrecv.flag = KICK;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
clientrecv.flag = BEEN_KICK;
writecnt = write(p->clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
else
{
prev->next = p->next;
free(p);
//p = NULL;
clientrecv.flag = KICK;
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
}
}
clientrecv.flag = KICK_FAIL; //踢人失败
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("view_friends");
return 0;
}
break;
}
}
case 26: //查看用户信息
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 0; i<= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
{
strcpy(clientrecv.sign,result[i*ncolumn + 3]);
clientrecv.vip = atoi(result[i*ncolumn + 2]);
clientrecv.flag = SHOW_INFO;
break;
}
}
}
write(clientfd,&clientrecv,sizeof(client));
break;
}
case 39: //注册会员
{
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int ret = 0;
int flag = 0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.username,result[i*ncolumn+ 0]) == 0)
{
sprintf(sql,"update account set vip = '%d' where username = '%s';",clientrecv.vip,clientrecv.username);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(ret != SQLITE_OK) //注册vip失败
{
perror("become vip");
return 0;
}
clientrecv.flag = VIP_SUCCESS;
}
}
}
write(clientfd,&clientrecv,sizeof(client));
break;
}
default:
{
break;
}
}
}
close(clientfd);
}
/*******************注册********************/
void register_client(int clientfd)
{
int ret = 0;
int writecnt = 0;
sprintf(sql,"insert into account(username,password,vip,sign,offline_msg)values('%s','%s',%d,'%s','%s');",clientrecv.username,clientrecv.password,clientrecv.vip,clientrecv.sign,clientrecv.offline_msg);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(ret != SQLITE_OK) //用户名已存在
{
clientrecv.flag = REG_FAIL;
}
else //成功创建新用户
{
clientrecv.flag = REG_SUCCESS;
}
writecnt = write(clientfd,&clientrecv,sizeof(client));
if(writecnt == -1)
{
perror("client:write");
//return -1;
}
}
#include "myhead.h"//client的主函数 :连接server并进行功能选择(注册,登录,退出)
void *read_msg_client(void *argc);
void menu(int socketfd);
void private_chat(int socketfd);
void group_chat(int socketfd);
void view_friends(int socketfd);
void correct_pin_number(int socketfd);
void off_line(int socketfd);
void admin_privilege(int socketfd);
void sign(int socketfd);
void send_offline_msg(int socketfd);
void become_vip(int socketfd);
void send_file(int socketfd);
void view_user_msg(int socketfd);;
sqlite3 *db = NULL;
char *errmsg = NULL;
char **result = NULL;
char sql[1024] = {0};
client clientsend;
client clientrecv;
char *my_time()
{
time_t now;
time(&now);
return (ctime(&now));
}
int showscreen()
{
int number = 0;
int flag = 0;
printf(" \n");
printf("********************************\n");
printf("* chatroom *\n");
printf("********************************\n");
printf("*1.注册用户 2.用户登录 *\n");
printf("*3.私聊 4.群聊 *\n");
printf("*5.查看在线好友 6.修改密码 *\n");
printf("*7.超级用户:禁言|解禁|踢人 *\n");
printf("*8.发送离线消息 9.发送文件 *\n");
printf("*10.个性签名 11.下线 *\n");
printf("*12.查看用户信息13.注册会员 *\n");
printf("********************************\n");
printf("\n");
printf("请输入选择的功能号:");
flag = scanf("%d",&number);
if(getchar() != '\n')
{
flag = 0;
}
while(flag != 1 || number < 0 || number > 13)
{
while(getchar() != '\n');
printf("输入错误!请重新输入:");
flag = scanf("%d",&number);
}
if(number >= 1 && number <= 13)
{
return number;
}
}
int main()
{
int socketfd = 0;
int ret = 0;
struct sockaddr_in server_addr;
pthread_t th;
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int number = 0; //用于注册登录界面
int flag = 0;
int writecnt = 0;
int readcnt = 0;
//client clientsend;
//client clientrecv;
socketfd = socket(AF_INET,SOCK_STREAM,0);
if(socketfd == -1)
{
perror("socket");
return -1;
}
printf("socket success...\n");
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MYPORT);
server_addr.sin_addr.s_addr = inet_addr(MYADDR);
ret = connect(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
if(ret == -1)
{
perror("connect");
return -1;
}
printf("connect success...\n");
while(1)
{
system("reset");
printf("1.注册用户\n");
printf("2.用户登录\n");
printf("3.退出\n");
printf("请输入选择的功能号:");
//登录时:忘记密码,修改密码
flag = scanf("%d",&number);
if(getchar() != '\n')
{
flag = 0;
}
while(flag != 1 || number < 0 || number > 3)
{
while(getchar() != '\n');
printf("输入错误!请重新输入:");
flag = scanf("%d",&number);
}
switch(number)
{
case 1: //注册
{
int i = 0;
int j = 0;
int temp = 0;
char secret[20] = {0}; //用于密码的保密
memset(&clientsend,0,sizeof(client));
clientsend.action = 1;
printf("用户名:");
scanf("%s",clientsend.username);
printf("密码:");
/*
for(i = 0; secret[i] != '\n'; i++)
{
secret[i] = getchar();
if(secret[i] == 10)
{
if(j == 0)
{
j++;
continue;
}
break;
}
printf("*");
}
secret[i] = '\0';
strcpy(clientsend.password,secret);
*/ scanf("%s",clientsend.password); //考虑确认密码的实现
printf("是否成为vip?(输入1:是,0:否): ");
temp = clientsend.vip;
scanf("%d",&temp);
writecnt = write(socketfd,&clientsend,sizeof(client)); //发送给server
if(writecnt == -1)
{
perror("client:write");
return -1;
}
else
{
printf("正在验证中。。。\n");
}
memset(&clientrecv,0,sizeof(client));
readcnt = read(socketfd,&clientrecv,sizeof(client));
if(clientrecv.flag == REG_SUCCESS)
{
printf("注册成功!\n");
getchar();
getchar();
}
else if(clientrecv.flag == REG_FAIL)
{
printf("用户名不合法,注册失败!\n");
getchar();
getchar();
}
break;
}
case 2: //登录
{
//memset(&clientsend,0,sizeof(client));
clientsend.action = 2;
printf("用户名:");
scanf("%s",clientsend.username);
printf("密码:");
scanf("%s",clientsend.password);
write(socketfd,&clientsend,sizeof(client));
memset(&clientrecv,0,sizeof(client));
read(socketfd,&clientrecv,sizeof(client));
if(clientrecv.flag == LOGIN_SUCCESS)
{
printf("登录成功!\n");
getchar();
getchar();
if(pthread_create(&th,NULL,read_msg_client,&socketfd) == -1) //创建线程
{
perror("client:pthread_create");
return -1;
}
menu(socketfd);
}
else if(clientrecv.flag == LOGIN_FAIL)
{
printf("用户名、密码不匹配,登录失败!\n");
getchar();
getchar();
}
else if(clientrecv.flag == LOGIN_EXIT)
{
printf("您已登录!\n");
getchar();
getchar();
}
break;
}
case 3:
{
exit(0);
}
default:
{
break;
}
}
}
close(socketfd);
return 0;
}
void *read_msg_client(void *argc)
{
int socketfd = *((int *)argc);
//int readcnt = 0;
while(1)
{
read(socketfd,&clientrecv,sizeof(client));
switch(clientrecv.flag)
{
case PRIVATE_SUCCESS: //私聊
{
printf("\n%s to you | %s :",clientrecv.fromname,my_time());
printf("%s\n",clientrecv.msg);
break;
}
case PRIVATE_FAIL: //私聊时查无此人
{
printf("查无此人。\n\n");
break;
}
case GROUP_SUCCESS: //群聊
{
printf("\n%s send | %s :",clientrecv.fromname,my_time());
printf("%s\n",clientrecv.msg);
break;
}
case VIEW_FRIENDS_SUCCESS: //查看在线好友链表
{
printf("\n好友:%s\n",clientrecv.username);
break;
}
case CORRECT_SUCCESS:
{
printf("\n%s 修改密码成功!\n",clientrecv.username);
break;
}
case CORRECT_FAIL:
{
printf("\n%s 新密码输入不一致!\n",clientrecv.username);
break;
}
case CORRECT_OLD:
{
printf("\n%s 原密码输入错误!\n",clientrecv.username);
break;
}
case OFF_LINE_SUCCESS:
{
exit(0);
}
case OFF_LINE_FAIL:
{
printf("\n%s 下线失败!\n",clientrecv.username);
break;
}
case BAN:
{
printf("\n%s 已被成功禁言!\n",clientrecv.toname);
}
case BAN_USER:
{
printf("\n您已被禁言!\n");
break;
}
case REMOVE:
{
printf("\n%s 已被成功解禁!\n",clientrecv.toname);
}
case REMOVE_USER:
{
printf("\n您已被解禁!\n");
break;
}
case KICK:
{
printf("\n%s 已被成功踢出!\n",clientrecv.toname);
break;
}
case KICK_FAIL:
{
printf("\n%s 未被踢出!\n",clientrecv.toname);
break;
}
case BEEN_KICK:
{
exit(0);
}
case NO_POWER:
{
printf("\n您没有VIP权限,不能进行该操作!\n");
//sleep(5);
break;
}
case SIGN_SUCCESS:
{
printf("\n成功修改个性签名!\n");
//sleep(5);
break;
}
case SEND_SUCCESS:
{
printf("\n离线消息发送成功\n");
break;
}
case FILE_SUCCESS:
{
char ch = '0';
int ret = 0;
printf("\n%s send a file to you | %s :",clientrecv.fromname,my_time());
printf("filename:%s\n",clientrecv.filename);
/* printf("你要接收该文件吗? y/n");
scanf(" %c",&ch);
while(ch != 'y' && ch != 'n')
{
while(getchar() != '\n');
printf("输入错误!请重新输入:");
scanf("%ch",&ch);
}
if(ch == 'y') //接收文件
*/ {
int fd = 0;
fd = open("new.txt",O_CREAT|O_RDWR|S_IRUSR|S_IWUSR);
if(fd < 0)
{
perror("open");
//return -1;
}
ret = write(fd,clientrecv.file,strlen(clientrecv.file));//从file数组中提取数据写入文件
printf("%s\n",clientrecv.file);
if(ret < 0)
{
perror("write");
//return -1;
}
break;
}
/* else if(ch == 'n') //拒收文件
{
break;
}
*/ }
case FILE_FAIL:
{
printf("\n查无此人\n");
break;
}
case VIP_SUCCESS:
{
printf("\n您已获得vip。\n");
break;
}
case SHOW_INFO:
{
printf("\n用户名:%s\n",clientrecv.username);
//while(getchar() != '\0');
printf("个性签名:%s\n",clientrecv.sign);
printf("是否为vip会员:");
if(clientrecv.vip == 1)
{
printf("是\n");
}
else
{
printf("不是\n");
}
break;
}
default:
{
break;
}
}
}
}
void menu(int socketfd)
{
int number = 0;
while(1)
{
system("reset");
number = showscreen();
system("reset");
switch(number)
{
case 3:
{
private_chat(socketfd); //私聊
break;
}
case 4:
{
group_chat(socketfd); //群聊
break;
}
case 5:
{
view_friends(socketfd); //查看在线好友链表
break;
}
case 6:
{
correct_pin_number(socketfd); //修改密码
break;
}
case 7:
{
admin_privilege(socketfd); //管理员权限:禁言|解禁|踢人
break;
}
case 8:
{
send_offline_msg(socketfd); //发送离线消息
break;
}
case 9:
{
send_file(socketfd); //发送文件
break;
}
case 10:
{
sign(socketfd); //修改个性签名
break;
}
case 11:
{
off_line(socketfd); //下线
//printf("成功退出!\n");
//exit(0);
}
case 12:
{
view_user_msg(socketfd); //查看用户信息
break;
}
case 13: //会员
{
become_vip(socketfd);
break;
}
default:
{
// printf("输入错误,请输入正确的功能号。\n");
// getchar();
// getchar();
break;
}
}
}
}
/******************私聊*******************************/
void private_chat(int socketfd)
{
char buff[500] = {0};
clientsend.action = PRIVATE_CHAT;
printf("请输入你要私聊的用户名:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
strcpy(clientsend.fromname,clientsend.username);
while(strcmp(clientsend.toname,clientsend.username) == 0)
{
while(getchar() != '\n');
printf("私聊对象不能为本身,请重新输入:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
}
while(1)
{
printf("请输入发送的内容:\n"); //我发送的信息内容
//scanf("%s",buff);
//strcpy(clientsend.msg,buff);
scanf("%s",clientsend.msg);
if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0 )
{
break;
}
write(socketfd,&clientsend,sizeof(client));
}
}
/*********************群聊*****************************/
void group_chat(int socketfd) //群聊
{
char buff[500] = {0};
while(1)
{
clientsend.action = GROUP_CHAT;
strcpy(clientsend.fromname,clientsend.username);
printf("请输入发送的内容:\n");
scanf("%s",buff);
strcpy(clientsend.msg,buff);
write(socketfd,&clientsend,sizeof(client));
if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0)
{
break;
}
}
}
/********************查看在线好友链表********************************/
void view_friends(int socketfd) //好友为0时,好友个数
{
char ch = '0';
while(1)
{
//int writecnt = 0;
clientsend.action = VIEW_FRIENDS;
write(socketfd,&clientsend,sizeof(client));
printf("请输入 'q' 返回主界面 :");
scanf("%c",&ch);
while(ch != 'q')
{
while(getchar() != '\n');
printf("输入错误! 请输入 'q' 返回主界面 :");
scanf(" %c",&ch);
}
if(ch == 'q')
{
break;
}
}
}
/**********************修改密码***********************************/
void correct_pin_number(int socketfd)
{
while(1)
{
char buff[20] = {0};
char ch = '0';
clientsend.action = CORRECT_PIN_NUMBER;
printf("请输入原密码 : ");
scanf("%s",buff);
strcpy(clientsend.password,buff);
memset(&buff,0,sizeof(char));
printf("请输入新密码 : ");
scanf("%s",buff);
strcpy(clientsend.new_passwd1,buff);
memset(&buff,0,sizeof(char));
printf("请再次输入新密码 : ");
scanf("%s",buff);
strcpy(clientsend.new_passwd2,buff);
write(socketfd,&clientsend,sizeof(client));
printf("请输入 'q' 返回主界面 :");
scanf("%c",&ch);
while(ch != 'q')
{
while(getchar() != '\n');
printf("输入错误! 请输入 'q' 返回主界面 :");
scanf(" %c",&ch);
}
if(ch == 'q')
{
break;
}
}
}
/*********************下线*****************************/
void off_line(int socketfd)
{
char ch = '0';
clientsend.action = OFF_LINE;
printf("确认下线吗? y/n : \n");
scanf("%c",&ch);
while(ch != 'n' && ch != 'y')
{
while(getchar() != '\n');
printf("输入错误! 请输入 y/n:\n");
scanf(" %c",&ch);
}
if(ch == 'y')
{
write(socketfd,&clientsend,sizeof(client));
}
else if(ch == 'n')
{
printf("返回主界面。\n");
}
}
/****************会员权限************************/
void admin_privilege(int socketfd)
{
while(1)
{
int number = 0;
int flag = 0;
char buff[20] = {0};
char ch = '0';
//clientsend.action = ADMINI_PRIVILEGE;
printf("1.禁言\n");
printf("2.解禁\n");
printf("3.踢人\n\n");
printf("请输入你选择的命令(数字):\n");
//scanf("&d",&number);
flag = scanf("%d",&number);
if(getchar() != '\n')
{
flag = 0;
}
while(flag != 1 || number < 1 || number > 3)
{
while(getchar() != '\n');
printf("输入错误!请重新输入:");
flag = scanf("%d",&number);
}
if(number == 1)
{
clientsend.action = BAN;
}
else if(number == 2)
{
clientsend.action = REMOVE;
}
else if(number == 3)
{
clientsend.action = KICK;
}
printf("请输入对象:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
write(socketfd,&clientsend,sizeof(client));
printf("\n是否继续? 请输入y/n:\n");
scanf(" %c",&ch);
while(ch != 'n' && ch != 'y')
{
while(getchar() != '\n');
printf("输入错误! 请输入y/n:\n");
scanf(" %c",&ch);
}
if(ch == 'n')
{
break;
}
}
}
/*********************发送文件************************/
void send_file(int socketfd)
{
char buff[1024] = {0};
char ch = 0;
int i = 0;
int ret = 0;
int temp = 0;
clientsend.action = SEND_FILE;
printf("请输入你要发送文件的对象:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
strcpy(clientsend.fromname,clientsend.username);
while(strcmp(clientsend.toname,clientsend.username) == 0)
{
while(getchar() != '\n');
printf("发送文件对象不能为本身,请重新输入:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
}
printf("请输入发送的文件名:\n");
scanf("%s",clientsend.filename);
int fd = 0;;
fd = open(clientsend.filename,O_RDONLY,S_IRUSR|S_IWUSR);
if(fd < 0)
{
printf("该文件不存在!");
//exit(-1);
temp = 1;
}
if(temp == 0)
{
while(1) //从文件中读取数据到file数组中
{
memset(&ch,0,sizeof(ch));
ssize_t read_bytes = read(fd,&ch,sizeof(ch));
if(read_bytes == -1)
{
perror("read");
//return -1;
}
if(read_bytes == 0) //读完退出循环
{
break;
}
clientsend.file[i] = ch;
i++;
}
clientsend.file[i] = '\0';
ret = write(socketfd,&clientsend,sizeof(client));
if(ret = -1)
{
perror("write");
//return -1;
}
}
}
/********************个性签名**********************/
void sign(int socketfd)
{
while(1)
{
char ch = '0';
char buff[50] = {0};
clientsend.action = SIGN;
printf("请输入你的个性签名:\n");
scanf("%s",buff);
strcpy(clientsend.sign,buff);
write(socketfd,&clientsend,sizeof(client));
printf("请输入 'q' 返回主界面 :");
scanf("%c",&ch);
while(ch != 'q')
{
while(getchar() != '\n');
printf("输入错误! 请输入 'q' 返回主界面 :");
scanf(" %c",&ch);
}
if(ch == 'q')
{
break;
}
}
}
/*****************发送离线消息*************************/
void send_offline_msg(int socketfd)
{
char buff[500] = {0};
while(1)
{
clientsend.action = SEND_OFFLINE_MSG;
printf("请输入你要发送离线消息的用户名:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
strcpy(clientsend.fromname,clientsend.username);
while(strcmp(clientsend.toname,clientsend.username) == 0)
{
while(getchar() != '\n');
printf("发送离线消息对象不能为本身,请重新输入:\n");
scanf("%s",buff);
strcpy(clientsend.toname,buff);
}
printf("请输入发送的内容:\n"); //我发送的信息内容
scanf("%s",buff);
strcpy(clientsend.msg,buff);
write(socketfd,&clientsend,sizeof(client));
if(strcmp(clientsend.msg,"end") == 0 || strcmp(clientsend.toname,"end") == 0)
{
break;
}
}
}
/*********************查看用户信息*************************/
void view_user_msg(int socketfd)
{
clientsend.action = VIEW_USER_MSG;
write(socketfd,&clientsend,sizeof(client));
}
/********************注册会员***********************/
void become_vip(int socketfd)
{
char buff[20] = {0};
char ch = '0';
int writecnt = 0;
while(1)
{
clientsend.action = BECOME_VIP;
printf("是否成为vip?(输入y:是,n:否):\n");
scanf(" %c",&ch);
while(ch != 'y' && ch != 'n')
{
while(getchar() != '\n');
printf("输入错误!请重新输入:");
scanf("%ch",&ch);
}
if(ch == 'y')
{
clientsend.vip = 1;
writecnt = write(socketfd,&clientsend,sizeof(client));
if(writecnt = -1)
{
perror("write ");
return 0;
}
}
else if(ch == 'n')
{
break;
}
}
}