#include "menu.h"
extern int cfd; //客户端与服务器之间的通讯套接字
extern int cltcfd; //客户端绑定的通讯套接字
extern struct sockaddr_in cltaddr; //客户端的地址结构体
node_t *online_head = NULL; //在线客户链表头节点
void *pthread_talk(void *login_info); //该线程用来聊天
//欢迎界面
void welcome_menu()
{
int n, i;
int ret = 0;
registe_info_t reg;
login_info_t login;
while(1)
{
system("clear");
welcome_window();
n = get_key();
switch(n)
{
case 0:
login.cmd = LOGIN; //登录协议
login.addr = cltaddr; //客户端地址结构体
login_menu(login.account, login.passwd);
send(cfd, &login, LOGSIZE, 0); //发送登录请求
recv(cfd, &ret, sizeof(int), 0); //接受服务器的响应
if (SUCCESS == ret)
{
printf("\e[10;56H登录成功\e[0m\n");
friend_menu(&login); //进入聊天界面
return ;
}
else
{
printf("\e[10;56H登录失败\e[0m\n");
}
sleep(1);
break;
case 1:
reg.cmd = REGISTE; //注册协议
registe_unregiste_menu(reg.account, reg.passwd);
send(cfd, ®, REGSIZE, 0); //发送注册请求
recv(cfd, &ret, sizeof(int), 0); //接受服务器的响应
if (SUCCESS == ret)
{
printf("\e[10;56H注册成功\e[0m\n");
}
else
{
printf("\e[10;56H注册失败\e[0m\n");
}
sleep(1);
break;
case 2:
reg.cmd = UNREGISTE; //注销协议
registe_unregiste_menu(reg.account, reg.passwd);//进入注销界面
send(cfd, ®, REGSIZE, 0); //发送注销请求
recv(cfd, &ret, sizeof(int), 0); //接受服务器的响应
if (SUCCESS == ret)
{
printf("\e[10;56H注销成功\e[0m\n");
}
else
{
printf("\e[10;56H注销失败\e[0m\n");
}
sleep(1);
break;
case 3:
reg.cmd = LOGOUT;
send(cfd, ®, REGSIZE, 0);
recv(cfd, &ret, sizeof(int), 0);
if (SUCCESS == ret)
return ;
else
perror("\e[10;56Hlogout error\e[0m\n");
break;
}
}
}
//帐号窗口
int account_window()
{
int i, j;
for (j = 40; j <= 80; j++)
printf("\e[2;%dH\e[45m%s", j, " ");
printf("\e[0m\n");
for (j = 40; j <= 80; j++)
printf("\e[8;%dH\e[45m%s", j, " ");
printf("\e[0m\n");
for (i = 3; i <= 7; i++)
{
for (j = 40; j <= 41; j++)
printf("\e[%d;%dH\e[45m%s", i, j, " ");
printf("\e[0m\n");
}
for (i = 3; i <= 7; i++)
{
for (j = 79; j <= 80; j++)
printf("\e[%d;%dH\e[45m%s", i, j, " ");
printf("\e[0m\n");
}
return 0;
}
/************************************************************
函数功能: 注册和注销的界面
参 数: account : 保存账号
passwd : 保存密码
返 回 值: 无
*************************************************************/
void registe_unregiste_menu(char *account, char *passwd)
{
char key[128] = {0};
system("clear");
account_window();
printf("\e[4;44H请输入帐号:");
fflush(NULL);
fgets(account, 32, stdin);
printf("\e[6;44H请输入密码:");
fflush(NULL);
// fgets(key, 128, stdin);
getpasswd(key);
strcpy(passwd, (char *)crypt(key, SALT));//用MD5加密密码 SALT: 自定义加密种子
printf("\n");
}
/************************************************************
函数功能: 登录的界面
参 数: account : 保存账号
passwd : 保存密码
返 回 值: 无
*************************************************************/
void login_menu(char *account, char *passwd)
{
char key[128] = {0};
system("clear");
account_window();
printf("\e[4;44H请输入帐号:");
fflush(NULL);
fgets(account, 32, stdin);
printf("\e[6;44H请输入密码:");
fflush(NULL);
// fgets(key, 128, stdin);
getpasswd(key);
strcpy(passwd, (char *)crypt(key, SALT));//用MD5加密密码 SALT: 自定义加密种子
printf("\n");
}
/************************************************************
函数功能: 好友界面
参 数: 登录结构体指针
返 回 值: 无
*************************************************************/
void friend_menu(login_info_t *login)
{
online_head = create_cirlist();
node_t *node;
char buf[128] = {0};
online_info_t *onl;
online_info_t friend; //用来接受在线好友
int flag, i = 0, j = 0;
char *account = login->account;
struct pollfd arr[2]; //poll结构体 实现服务器与客户端之间 非阻塞接收与发送信息
arr[0].fd = 0; //标准输入描述符
arr[0].events = POLLIN;
arr[1].fd = cfd; //服务器与客户端之间 通讯套接字
arr[1].events = POLLIN;
while (1)
{
system("clear");
online_window();
printf("%s\n", login->account); //刷新自己的账号
fflush(NULL);
printf("\e[12;4H%s\e[0m\n", "好友信息:");
node = online_head->next;
while (node != online_head) //循环遍历其它上线的客户端的账号
{
onl = (online_info_t *)(node->data);
printf("\e[45m%s\e[0m", " ");
printf("\e[47m%s%s\e[0m", " 渠道新班 ", onl->account);
fflush(NULL);
node = node->next;
}
printf("\e[25;35H"); //////
fflush(NULL);
while (1)
{
poll(arr, 2, -1); //poll 函数调用
if (POLLIN == arr[0].revents)
{
flag = 1;
break ; //
}
if (POLLIN == arr[1].revents)
{
if (0 == recv(cfd, &friend, ONLSIZE, 0))
return ;
if (OVER == *(int *)&friend) //在线好友加载完成
break;
if (NULL == find_cirlist_account(online_head, friend.account, onl_cmp_account))//没有此人就插入链表
{
insert_cirlist_t(online_head, &friend, ONLSIZE); //将在线好友加载到在线链表尾
}
else //否则就删除
{
cirlist_info_del(online_head, friend.account, onl_cmp_account); //
}
}
}
if (1 == flag)
{
flag = 0;
bzero(buf, 128);
read(0, buf, 128);
if (0 == strcmp(buf, "quit\n")) //发送下线命令
{
login->cmd = UNLINE;
send(cfd, login, LOGSIZE, 0);
return ;
}
else if (0 == strcmp(buf, "##GROUP\n")) //群聊提示标志
{
group_talk(online_head, login); //调用群聊函数
}
else
{
onl = find_cirlist_account(online_head, buf, onl_cmp_account); //查找聊天对象是否存在
if (onl != NULL)
talk(onl, login); //进行客户端与客户端的聊天
else
{
printf("\e[45m%s\e[0m", " ");
printf("\e[20;37H\e[35m%s\e[0m\n"," 不在线 ");
sleep(1);
printf("\e[25;35H"); //////
fflush(NULL);
}
}
//////////////////////////
}
}
}
//起始窗口(登录页面)
int welcome_window()
{
int i, j;
for (j = 40; j <= 80; j++)
printf("\e[2;%dH \e[43m\n", j);
printf("\e[0m\n");
for (i = 2; i <= 20; i++)
{
for (j = 40; j <= 41; j++)
printf("\e[%d;%dH\e[43m%s\n", i, j, " ");
printf("\e[0m\n");
}
for (i = 2; i <= 20; i++)
{
for (j = 79; j <= 80; j++)
printf("\e[%d;%dH\e[43m%s\n", i, j, " ");
printf("\e[0m\n");
}
for (j = 41; j <= 79; j++)
printf("\e[6;%dH\e[43m%s", j, " ");
for (j = 40; j <= 80; j++)
printf("\e[21;%dH\e[43m%s", j, " ");
printf("\e[0m\n");
for (j = 41; j <= 79; j++)
printf("\e[17;%dH\e[43m%s", j, " ");
printf("\e[4;52H\e[31m\e[43m%s\e[0m\n", "欢迎使用 QQ 2018");
printf("\e[19;54H\e[31m\e[43m%s\e[0m\n", "有志者,事竟成");
printf("\e[10;57H\e[7m%s\e[0m\n", "登 录");
printf("\e[11;57H%s\e[0m\n", "注 册");
printf("\e[12;57H%s\e[0m\n", "注 销");
printf("\e[13;57H%s\e[0m\n", "退 出");
return 0;
}
//捕捉按键
int get_key()
{
tcgetattr(0, &oldattr);
cfmakeraw(&newattr);
int ret,val = -1,sel_flag = 0;
char key[3]= {0};
while(1)
{
memset(key,0,3);
tcsetattr(0,TCSANOW,&newattr);
ret = read(0,key,3);
tcsetattr(0,TCSANOW,&oldattr);
if(ret == 1)
{
if(key[0] == 13)
return sel_flag;
}
if(ret == 3)
{
if(key[0] == 27 && key[1] == 91 && key[2] == 66)
{
sel_flag += 1;
if(sel_flag == 4)
sel_fl