这里,我对客户端代码进行了模块化优化,并优化了界面,加上了注释
流程图:
模块化划分:
共分为一下几个模块:
mian.cpp :
socket启动及链接,开启线程
logic.cpp
功能函数:对应了登陆与注册,私聊,群聊,文件传输,好友和群组管理函数
tools.cpp
工具函数:求文件大小,发送包,和一些判断函数
view.cpp
显示的界面函数:菜单显示函数,聊天界面函数,信息查看函数
client.h
结构体声明,函数声明,全局变量声明
下面是客户端的界面截图
登陆界面:
主界面:
好友查看界面:
聊天界面:
文件发送界面:
文件接收界面:
文件消息盒子界面:
聊天记录界面:
下面上代码(已加详细注释):
main.cpp
#include <mysql/mysql.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <termios.h>
/*****************same with server**********************/
#define LOGIN 1
#define REGISTER 2
#define FRIEND_SEE 3
#define FRIEND_ADD 4
#define FRIEND_DEL 5
#define GROUP_SEE 6
#define GROUP_CREATE 7
#define GROUP_JOIN 8
#define GROUP_QIUT 9
#define GROUP_DEL 10
#define CHAT_ONE 11
#define CHAT_MANY 12
#define FILE_SEND_BEGIN 13
#define FILE_SEND_BEGIN_RP 14
#define FILE_SEND_STOP_RP 15
#define FILE_RECV_RE 16
#define FILE_SEND 17
#define FILE_RECV_BEGIN 18
#define FILE_RECV_BEGIN_RP 19
#define FILE_RECV_STOP_RP 20
#define FILE_RECV 21
#define FILE_FINI_RP 22
#define MES_RECORD 23
#define EXIT -1
#define SIZE_PASS_NAME 10
#define MAX_PACK_CONTIAN 100
#define MAX_CHAR 300
#define NUM_MAX_DIGIT 10
#define DOWNLINE 0
#define ONLINE 1
#define BUZY 2
/**************************************************/
typedef struct friend_info
{
int statu;
int mes_num;
char name[MAX_CHAR];
}FRIEND_INFO;
typedef struct user_infor{
char username [MAX_CHAR];
FRIEND_INFO friends [MAX_CHAR];
int friends_num;
char group [MAX_CHAR][MAX_CHAR];
int group_num;
}USER_INFOR;
/******************be sure same with server*******************************/
typedef struct datas{
char send_name[MAX_CHAR];
char recv_name[MAX_CHAR];
int send_fd;
int recv_fd;
//time_t time;
char mes[MAX_CHAR*2];
}DATA;
typedef struct package{
int type;
DATA data;
}PACK;
typedef struct pthread_parameter
{
int a;
int b;
}PTHREAD_PAR;
typedef struct prinit_mes
{
char name[MAX_CHAR];
char time[MAX_CHAR];
char mes [MAX_CHAR];
}PRINT_MES;
typedef struct sockaddr SA;
void init();
void *deal_statu(void *arg);
void *clien_recv_thread(void *arg);
void init_clien_pthread();
int main_menu();
int send_login(char username_t[],char password_t[]);
int login();
int send_registe(char username_t[],char password_t[]);
void registe();
void get_status_mes();
void change_statu(PACK pack_deal_statu_t);
void add_friend();
void del_friend();
void group_create();
void group_join();
void group_qiut();
void group_del();
void send_mes_to_one();
void send_mes_to_group();
void send_mes(char mes_recv_name[],int type);
void *show_mes(void *username);
void print_mes(int id);
void send_file();
void *pthread_send_file(void *mes_t);
void send_file_send(int begin_location,char *file_path);
int file_mes_box();
void deal_file_mes(int id);
void mes_sendfile_fail(int id);
void mes_recv_requir(int id);
void mes_recvfile_fail(int id);
void *pthread_recv_file(void *par_t);
int mes_record();
void print_mes_record(PACK* pack_t);
int login_menu();
void show_mes_smart(char *name ,char *mes);
void friends_see();
void group_see();
void print_main_menu();
void my_err(const char * err_string,int line);
void sig_close(int i);
int get_file_size(char *file_name);
void file_infor_delete(int id);
int judge_same_group(char *group_name);
int judge_same_friend(char add_friend_t[]);
int get_choice(char *choice_t);
void send_pack(int type,char *send_name,char *recv_name,char *mes);
void send_pack_memcpy(int type,char *send_name,char *recv_name,char *mes);
USER_INFOR m_my_infor;
/*****************send*********************/
PACK m_pack_send [MAX_CHAR];
int m_send_num;
/*****************recv*********************/
PACK m_pack_recv_friend_see [MAX_PACK_CONTIAN];
PACK m_pack_recv_chat [MAX_PACK_CONTIAN];
PACK m_pack_recv_send_file [MAX_PACK_CONTIAN];
PACK m_pack_recv_file_mes [MAX_PACK_CONTIAN];
PACK m_pack_recv_file [MAX_PACK_CONTIAN];
int m_recv_num_friend_see;
int m_recv_num_chat;
int m_recv_num_send_file;
int m_recv_num_file_mes;
int m_recv_num_file;
int m_print_mes_flag;
/****************************************************/
int m_flag_group_create;
int m_flag_group_join ;
int m_flag_group_del ;
int m_flag_print_mes;
int m_flag_print_recorde;
// int window_col;
// int window_row;
/****************************************************/
PRINT_MES m_print_mes[10];
int m_print_mes_num;
/***********************function***********************/
int sockfd;
char *IP = "115.159.205.168";
short PORT = 11112;
typedef struct sockaddr SA;
pthread_mutex_t mutex_local_user;
pthread_mutex_t mutex_recv_file;
void init()
{
printf("客户端开始启动\n");
sockfd = socket(AF_INET,SOCK_STREAM,0);//启动socket
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
if(connect(sockfd,(SA*)&addr,sizeof(addr))==-1){
perror("无法连接到服务器");
printf("客户端启动失败\n");
exit(-1);
}
printf("客户端启动成功\n");
}
/***************************
* 根据发来数据包及时更新
* 好友状态
* *************************/
void *deal_statu(void *arg)
{
int i;
while(1)
{
pthread_mutex_lock(&mutex_local_user);
for(i=1;i<=m_recv_num_friend_see;i++)
{
//printf("flag1\n");
change_statu(m_pack_recv_friend_see[i]);
}
m_recv_num_friend_see = 0;
pthread_mutex_unlock(&mutex_local_user);
usleep(1);
}
}
/***************************
* 一直接收客户端发来的包
* 并把包存储到数组当中
* *************************/
void *clien_recv_thread(void *arg)
{
int i;
PACK pack_t;
pthread_t pid_send_file;
while(1)
{
if(recv(sockfd,&pack_t,sizeof(PACK),0) < 0){
my_err("recv",__LINE__);
}
//for(int i=1;i <= )
pthread_mutex_lock(&mutex_local_user);
for(int i=1 ;i<= m_my_infor.friends_num;i++)
{
if(strcmp(m_my_infor.friends[i].name,pack_t.data.send_name) == 0)
{
m_my_infor.friends[i].mes_num++;
break;
}
}
switch(pack_t.type)
{
case FRIEND_SEE:
m_pack_recv_friend_see[++m_recv_num_friend_see] = pack_t;
break;
case GROUP_CREATE:
m_flag_group_create = pack_t.data.mes[0];
break;
case GROUP_JOIN:
m_flag_group_join = pack_t.data.mes[0];
break;
case GROUP_DEL:
m_flag_group_del = pack_t.data.mes[0];
case CHAT_ONE:
m_pack_recv_chat[++m_recv_num_chat] = pack_t;
break;
case CHAT_MANY:
m_pack_recv_chat[++m_recv_num_chat] = pack_t;
break;
//case SEND_FILE:
// m_pack_recv_send_file[++m_recv_num_send_file] = pack_t;
//break;
case FILE_SEND_BEGIN_RP:
pthread_create(&pid_send_file,NULL,pthread_send_file,(void *)pack_t.data.mes);
break;
case FILE_SEND_STOP_RP:
m_pack_recv_file_mes[++m_recv_num_file_mes] = pack_t;
break;
case FILE_RECV_BEGIN:
m_pack_recv_file_mes[++m_recv_num_file_mes] = pack_t;
break;
case FILE_RECV:
pthread_mutex_lock(&mutex_recv_file);
m_pack_recv_file[++m_recv_num_file] = pack_t;
pthread_mutex_unlock(&mutex_recv_file);
break;
case FILE_RECV_STOP_RP:
m_pack_recv_file_mes[++m_recv_num_file_mes] = pack_t;
break;
case MES_RECORD:
PACK *pack_record = (PACK *)malloc(sizeof(PACK));
memcpy(pack_record,&pack_t,sizeof(PACK));
print_mes_record(pack_record);
break;
}
pthread_mutex_unlock(&mutex_local_user);
usleep(1);
}
}
//开启线程
void init_clien_pthread()
{
pthread_t pid_deal_statu,pid_recv,pid_recv_file;
pthread_create(&pid_deal_statu,NULL,deal_statu,NULL);
pthread_create(&pid_recv,NULL,clien_recv_thread,NULL);
}
//主菜单
int main_menu()
{
char choice_t[100];
int chioce;
do
{
get_status_mes();
//printf("pack num_chat:%d\n", m_recv_num_chat);
print_main_menu();
scanf("%s",choice_t);
chioce = get_choice(choice_t);
switch(chioce)
{
case 1:
friends_see();
break;
case 2:
add_friend();
break;
case 3:
del_friend();
break;
case 4:
group_see();
break;
case 5:
group_create();
break;
case 6:
group_join();
break;
case 7:
group_qiut();
break;
case 8:
group_del();
break;
case 9:
send_mes_to_one();
break;
case 10:
send_mes_to_group();
break;
case 11:
send_file();
break;
case 12:
file_mes_box();
break;
case 13:
mes_record();
default:
break;
}
}while(chioce!=0);
return 0;
}
int main(int argc, char const *argv[])
{
int flag =0;
// struct winsize size;
signal(SIGINT,sig_close);//关闭CTRL+C
init();//启动并连接服务器
// ioctl(STDIN_FILENO,TIOCGWINSZ,&size); //get size of window
// window_col = size.ws_col;
// window_row = size.ws_row;
if(login_menu() == 0)//判断是否登陆成功
return 0;
init_clien_pthread();//开启线程
main_menu(); //主菜单
return 0;
}
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/
logic.cpp
#include "client.h"
/*
* 向服务端发送登陆信息
*/
int send_login(char username_t[],char password_t[])
{
PACK recv_login_t;
int login_judge_flag = 0;
send_pack(LOGIN,username_t,"server",password_t);
if(recv(sockfd,&recv_login_t,sizeof(PACK),0) < 0){
my_err("recv",__LINE__);
}
login_judge_flag = recv_login_t.data.mes[0] - 48;
return login_judge_flag;
}
/*
* 根据输入信息向客户端发送登陆请求
* 并根据返回内容,提示用户
*/
int login()
{
int flag = 0;
int login_flag = 0;
char username_t [MAX_CHAR];
char password_t [MAX_CHAR];
printf("please input the username:\n");
scanf("%s",username_t);
printf("please input the password\n");
scanf("%s",password_t);
login_flag = send_login(username_t,password_t);
if(login_flag == 2){
printf("\033[;31mthe username is not exit.\033[0m\n");
return 0;
}
if(login_flag == 3 ){
printf("\033[;31mthe user has loged in .\033[0m\n");
return 0;
}
if(login_flag == 0) {
printf("\033[;31mthe password is not crrect.\033[0m\n");
return 0;
}
strcpy(m_my_infor.username,username_t);
printf("\033[;32mload successfully!\033[0m\n");
return 1;
}
/*
* 向服务端发送注册信息
*/
int send_registe(char username_t[],char password_t[])
{
PACK recv_registe_t;
int send_registe_flag;
send_pack(REGISTER,username_t,"server",password_t);
if(recv(sockfd,&recv_registe_t,sizeof(PACK),0) < 0){
my_err("recv",__LINE__);
}
send_registe_flag = recv_registe_t.data.mes[0] - 48;
return send_registe_flag;
}
/*
* 根据输入信息向客户端发送注册请求
* 并根据返回内容,提示用户
*/
void registe()
{
int flag = 0;
flag = REGISTER;
char username_t[MAX_CHAR];
char password_t[MAX_CHAR];
printf("please input the username you want register:\n");
scanf("%s",username_t);
printf("please input the password you want register:\n");
scanf("%s",password_t);
if(send_registe(username_t,password_t))
printf("\033[;32mregiste successfully!\033[0m\n");
else
printf("\033[;31mthe name is used ,please input another one\033[0m\n");
}
/*
* 向服务端请求更新好友状态
*/
void get_status_mes()
{
PACK pack_friend_see;
pack_friend_see.type = FRIEND_SEE;
strcpy(pack_friend_see.data.send_name,m_my_infor.username);
strcpy(pack_friend_see.data.recv_name,"server");
memset(pack_friend_see.data.mes,0,sizeof(pack_friend_see.data.mes));
if(send(sockfd,&pack_friend_see,sizeof(PACK),0) < 0){
my_err("send",__LINE__);
}
}
//根据服务端发送来的包,利用字符串解析,更新当前好友状态
void change_statu(PACK pack_deal_statu_t)
{
int count = 0;
m_my_infor.friends_num=pack_deal_statu_t.data.mes[count++];
//更新好友信息
for(int i=1; i <= m_my_infor.friends_num ;i++)
{
for(int j=0;j<SIZE_PASS_NAME;j++)
{
if(j == 0)
m_my_infor.friends[i].statu = pack_deal_statu_t.data.mes[count+j] - 48;
else
m_my_infor.friends[i].name[j-1] = pack_deal_statu_t.data.mes[count+j];
}
count += SIZE_PASS_NAME;
}
//更新群组信息
m_my_infor.group_num=pack_deal_statu_t.data.mes[count++];
for(int i=1 ;i <= m_my_infor.group_num ;i++)
{
for(int j=0;j<SIZE_PASS_NAME;j++)
{
m_my_infor.group[i][j] = pack_deal_statu_t.data.mes[count+j];
}
count += SIZE_PASS_NAME;
}
}
/**************************************/
//添加好友
void add_friend()
{
char add_friend_t[MAX_CHAR];
printf("please input the name of friend you want to add:\n");
scanf("%s",add_friend_t);
if(strcmp(add_friend_t,m_my_infor.username) == 0)
{
printf("you can't add youself to be your friend!\n");
return;
}
//判断是否已经添加过该好友
if(judge_same_friend(add_friend_t))
{
printf("you already have same friends!\n");
return ;
}
printf("m_my_infor.username:%s\n", m_my_infor.username);
send_pack(FRIEND_ADD,m_my_infor.username,"server",add_friend_t);
get_status_mes();
}
//删除好友
void del_friend()
{
char del_friend_t[MAX_CHAR];
printf("please input the name of friend you want to delete:\n");
scanf("%s",del_friend_t);
//判断是否添加过该好友
if(!judge_same_friend(del_friend_t))
{
printf("you don't have this friends on list!\n");
return ;
}
printf("m_my_infor.username:%s\n", m_my_infor.username);
//发送包
send_pack(FRIEND_DEL,m_my_infor.username,"server",del_friend_t);
//得到状态信息
get_status_mes();
}
//创建群组
void group_create()
{
char group_name[MAX_CHAR];
printf("please input the group name you want to create:\n");
scanf("%s",group_name);
send_pack(GROUP_CREATE,m_my_infor.username,"server",group_name);
while(!m_flag_group_create);
printf("m_flag_group_create=%d\n", m_flag_group_create);
if(m_flag_group_create == 2)
printf("create group successfully!\n");
else if(m_flag_group_create == 1)
printf("this group has been created!\n");
m_flag_group_create = 0;
}
//加入群组
void group_join()
{
char group_name[MAX_CHAR];
printf("please input the group name you want to join:\n");
scanf("%s",group_name);
//判断是否已经加入该群
for(int i=1;i <= m_my_infor.group_num ;i++)
{
if(strcmp(m_my_infor.group[i],group_name) == 0)
{
printf("you have join this group!\n");
return ;
}
}
send_pack(GROUP_JOIN,m_my_infor.username,"server",group_name);
while(!m_flag_group_join);
if(m_flag_group_join == 2)
printf("join group successfully!\n");
else if(m_flag_group_join == 1)
printf("there is no group named %s\n",group_name);
m_flag_group_join = 0;
}
//退出群组
void group_qiut()
{
char group_name[MAX_CHAR];
printf("please input the group name you want to qiut:\n");
scanf("%s",group_name);
//判断是否添加过该群组
for(int i=1;i <= m_my_infor.group_num ;i++)
{
if(strcmp(m_my_infor.group[i],group_name) == 0)
{
send_pack(GROUP_QIUT,m_my_infor.username,"server",group_name);
printf("quit group %s successfully!\n",group_name);
return ;
}
}
printf("you did't join this group!\n");
}
//解散群
void group_del()
{
char group_name[MAX_CHAR];
printf("please input the group name you want to delete:\n");
scanf("%s",group_name);
for(int i=1;i <= m_my_infor.group_num ;i++)
{
if(strcmp(m_my_infor.group[i],group_name) == 0)
{
send_pack(GROUP_DEL,m_my_infor.username,"server",group_name);
while(!m_flag_group_del);
printf("m_flag_group_del=%d\n", m_flag_group_del);
if(m_flag_group_del == 2)
printf("delete group successfully!\n");
else if(m_flag_group_del == 1)
printf("you isn't the owner of group %s\n",group_name);
return ;
}
}
printf("you did't join this group!\n");
}
/*************************************************/
//私聊
void send_mes_to_one()
{
pthread_t pid;
int id;
char mes_recv_name[MAX_CHAR];
friends_see();//print friend list !
printf("please input the name you want to chat\n");
scanf("%s",mes_recv_name);
if (!(id=judge_same_friend(mes_recv_name)))
{
printf("sorry,you don't have the friend named !%s\n",mes_recv_name);
return ;
}
printf("\33[2J \33[1;1H\033[;33m\33[1m-^-^-^-^-^-^-^-^-^-^-message-^-^-^-^-^-^-^-^-^-^-\033[0m");
printf("\33[26B\n");
m_flag_print_mes = 1;
m_my_infor.friends[id].mes_num = 0;
//开启线程显示信息
pthread_create(&pid,NULL,show_mes,(void *)mes_recv_name);
send_mes(mes_recv_name,CHAT_ONE);
}
//群聊
void send_mes_to_group()
{
pthread_t pid;
char mes_recv_group_name[MAX_CHAR];
group_see();
printf("please input the group you want to chat\n");
scanf("%s",mes_recv_group_name);
if (!judge_same_group(mes_recv_group_name))
{
printf("sorry,you don't have the group named !%s\n",mes_recv_group_name);
return ;
}
m_flag_print_mes = 1;
printf("\33[2J \33[1;1H\033[;33m\33[1m-^-^-^-^-^-^-^-^-^-^-message-^-^-^-^-^-^-^-^-^-^-\033[0m");
printf("\33[26B\n");
//开启线程显示信息
pthread_create(&pid,NULL,show_mes,(void *)mes_recv_group_name);
send_mes(mes_recv_group_name,CHAT_MANY);
}
//接收用户输入并发送信息到客户端
void send_mes(char mes_recv_name[],int type)
{
PACK pack_send_mes;
char mes[MAX_CHAR];
time_t timep;
getchar();
printf("\033[;34m\33[1m-^-^-^-^-^-^-^-^-^-^-please input-^-^-^-^-^-^-^-^-^-^-\033[0m\n");
while(1)
{
time(&timep);
memset(mes,0,sizeof(mes));
printf("\33[s");
fflush(stdout);
//if(type == CHAT_ONE)
// printf("%s->",m_my_infor.username);
fgets(mes,MAX_CHAR,stdin);
while(mes[0] == 10)
{
printf("\33[1A");
fflush(stdout);
fgets(mes,MAX_CHAR,stdin);
}
//当用户输入quit时退出
if(strcmp(mes,"quit\n") == 0)
break;
printf("\33[u");
fflush(stdout);
printf("\33[s");
fflush(stdout);
printf("\33[K\n\33[K\n\33[K\n");
fflush(stdout);
printf("\33[u");
fflush(stdout);
//输入的的同时,输出信息
show_mes_smart(m_my_infor.username ,mes);
//printf("\t%s\n%s\n", m_my_infor.username,ctime(&timep),mes);
//发送给客户端
send_pack(type,m_my_infor.username,mes_recv_name,mes);
}
m_flag_print_mes = EXIT;
}
/*
* 在聊天的同时启动,启动线程读取,存储区域的
* 消息,并显示出来
*/
void *show_mes(void *username)
{
int id;
char *user_name = (char *)username;
while(1)
{
//如果退出聊天,就不再显示
if (m_flag_print_mes == EXIT)
break;
pthread_mutex_lock(&mutex_local_user);
id = 0;
//检索信息
for(int i = 1 ;i <= m_recv_num_chat; i++)
{
if(strcmp(m_pack_recv_chat[i].data.send_name,user_name) == 0)
{
id = i;
//输出信息
print_mes(id);
m_recv_num_chat--;
for(int j = id; j <= m_recv_num_chat&&m_recv_num_chat ;j++)
{
m_pack_recv_chat[j] = m_pack_recv_chat[j+1];
}
break;
}
}
pthread_mutex_unlock(&mutex_local_user);
usleep(1);
}
}
//根据寻找到的包把信息输出
void print_mes(int id)
{
char group_print_name[MAX_CHAR];
memset(group_print_name,0,sizeof(group_print_name));
if(m_pack_recv_chat[id].type == CHAT_ONE)
{
show_mes_smart(m_pack_recv_chat[id].data.send_name,m_pack_recv_chat[id].data.mes);
}
else
{
for(int i=0;i<SIZE_PASS_NAME;i++)
{
group_print_name[i] = m_pack_recv_chat[id].data.mes[i];
}
show_mes_smart( group_print_name,m_pack_recv_chat[id].data.mes+SIZE_PASS_NAME);
}
}
/*******************************************/
/*
* 向服务端请求发送文件,并将文件的大小
* 发送给服务端
*/
void send_file()
{
char recv_name[MAX_CHAR];
char file_path[MAX_CHAR];
int file_size_t;
char mes_t[MAX_CHAR];
friends_see();
printf("please input the friend name:\n");
scanf("%s",recv_name);
int id = judge_same_friend(recv_name);
if(id == 0)
{
printf("you don't hava this friend!\n");
return ;
}
printf("please input the path of file you want to send :\n");
scanf("%s",file_path);
//得到文件的大小
file_size_t = get_file_size(file_path);
printf("file_size :%d\n", file_size_t);
if(file_size_t == 0)
{
printf("please input creact file path\n");
return ;
}
//字符串分析
int digit = 0;
while(file_size_t != 0)
{
mes_t[digit++] = file_size_t%10;
file_size_t /= 10;
}
mes_t[digit] = -1;
for(int i=0 ;i< SIZE_PASS_NAME ;i++)
{
mes_t[NUM_MAX_DIGIT+i] = file_path[i];
}
//发送请求
send_pack_memcpy(FILE_SEND_BEGIN,m_my_infor.username,recv_name,mes_t);
}
//当接收到允许发送的消息时,开启线程发送文件
void *pthread_send_file(void *mes_t)
{
char *mes = (char *)mes_t;
int begin_location = 0;
char file_name[MAX_CHAR];
printf("\033[;31m \nfunction:pthread_send_file\033[0m \n");
//解析到服务端已接收文件大小
for(int i=0 ;i<NUM_MAX_DIGIT ;i++)
{
if(mes[i] == -1)
break;
int t1 = 1;
for(int l=0;l<i;l++)
t1*=10;
begin_location += (int)mes[i]*t1;
}
strcpy(file_name,mes+NUM_MAX_DIGIT);
send_file_send(begin_location,file_name);
}
//从起始位置向服务端发送文件
void send_file_send(int begin_location,char *file_path)
{
int fd;
int length;
int file_size;
int sum = begin_location;
char mes[MAX_CHAR*2];
printf("\33[2J\33[1;1H\n");
printf("\033[;34m\33[1m^-^-^-^-^-^-^-^-^-^happychat^-^-^-^-^-^-^-^-^-^\033[0m\n");
printf("\n\nsending the file.........\n");
//打开文件
if((fd = open(file_path,O_RDONLY)) == -1)
{
my_err("open",__LINE__);
return ;
}
file_size=lseek(fd, 0, SEEK_END);
printf("file_size=%d",file_size);
//文件内部指针移动
lseek(fd ,begin_location ,SEEK_SET);
bzero(mes, MAX_CHAR*2);
// 每读取一段数据,便将其发送给客户端,循环直到文件读完为止
while((length = read(fd ,mes+NUM_MAX_DIGIT ,MAX_CHAR*2 - NUM_MAX_DIGIT)) > 0)
{
sum += length;
// printf("length = %d\n", length);
int digit = 0;
while(length != 0)
{
mes[digit++] = length%10;
length /= 10;
}
mes[digit] = -1;
int color;
int jindu=(int)((double)sum/file_size*100);
printf("have sended :");
for(int i = 0 ;i<jindu/10;i++)
{
color = i%6;
printf("\033[;%dm\33[1m=\033[0m",color+32);
fflush(stdout);
}
printf("\033[;31m\33[1m>\033[0m");
fflush(stdout);
for(int j = 0;j<10-jindu/10;j++)
{
printf(" ");
fflush(stdout);
}
printf("\033[;31m\33[1m|\033[0m %d%% %d \n",jindu,sum);
send_pack_memcpy(FILE_SEND,m_my_infor.username,file_path,mes);
if(sum == file_size)
break;
bzero(mes, MAX_CHAR*2);
usleep(100000);
printf("\33[1A\33[K");
fflush(stdout);
}
// 关闭文件
close(fd);
printf("send finished!!\n");
print_main_menu();
}
/*
* 显示文件处理消息,并根据提供选择
*/
int file_mes_box()
{
char choice_t[100];
int chioce;
do
{
get_status_mes();
printf("\033[;34m\33[1m^-^-^-^-^-^-^-^-^-^file mes box^-^-^-^-^-^-^-^-^-^\033[0m\n");
for(int i = 1; i <= m_recv_num_file_mes;i++)
{
if(m_pack_recv_file_mes[i].type == FILE_SEND_STOP_RP)
printf("\t\033[;34m\33[1m*\033[0m \033[;31m\33[1msend file %s filed\033[0m \n",m_pack_recv_file_mes[i].data.send_name);
if(m_pack_recv_file_mes[i].type == FILE_RECV_BEGIN)
printf("\t\033[;34m\33[1m*\033[0m \033[;33m\33[1m%s send file %s to you\033[0m \n", m_pack_recv_file_mes[i].data.send_name,m_pack_recv_file_mes[i].data.mes+SIZE_PASS_NAME);
if(m_pack_recv_file_mes[i].type == FILE_RECV_STOP_RP)
printf("\t\033[;34m\33[1m*\033[0m \033[;31m\33[1mrecv file %s filed\033[0m \n", m_pack_recv_file_mes[i].data.mes+NUM_MAX_DIGIT);
}
printf("\t\033[;34m\33[1m*\033[0m 0.exit \n");
printf("\033[;34m\33[1m^-^-^-^-^-^-^-^-^-^end^-^-^-^-^-^-^-^-^-^-^-^-^-^-\033[0m\n");
printf("\t\tchoice:");
scanf("%s",choice_t);
chioce = get_choice(choice_t);
//进行处理
if(chioce != -1)
deal_file_mes(chioce);
}while(chioce!=0);
return 0;
}
//对文件信息进行分类处理
void deal_file_mes(int id)
{
if(m_pack_recv_file_mes[id].type == FILE_SEND_STOP_RP)
{
mes_sendfile_fail(id);
}
else if(m_pack_recv_file_mes[id].type == FILE_RECV_BEGIN)
{
mes_recv_requir(id);
}else if(m_pack_recv_file_mes[id].type == FILE_RECV_STOP_RP)
{
mes_recvfile_fail(id);
}
}
//处理文件上传失败,并询问是否重发
//进行断点续传
void mes_sendfile_fail(int id)
{
char chioce[10];
//解析已经上传的字节数
int begin_location = 0;
for(int i=0 ;i<NUM_MAX_DIGIT ;i++)
{
if( m_pack_recv_file_mes[id].data.mes[i] == -1)
break;
printf("%d\n\n",m_pack_recv_file_mes[id].data.mes[i]);
int t1 = 1;
for(int l=0;l<i;l++)
t1*=10;
begin_location += (int)m_pack_recv_file_mes[id].data.mes[i] * t1;
}
//询问是否重传
int file_size_t = get_file_size(m_pack_recv_file_mes[id].data.send_name);
printf("\033[;31m\33[1mthe file %s send failed ,have sended \033[;32m%d%%\033[;31m,do you want send again?\033[0m\n", m_pack_recv_file_mes[id].data.send_name,(int)((double)begin_location/file_size_t*100));
printf("y/n :");
scanf("%s",chioce);
if(chioce[0] != 'Y' && chioce[0] != 'y')
{
file_infor_delete(id);
return ;
}
//进行重传
send_file_send(begin_location,m_pack_recv_file_mes[id].data.send_name);
file_infor_delete(id);
}
//处理下载文件请求,询问是否接收文件
void mes_recv_requir(int id)
{
pthread_t pid_recv_file;
char choice[10];
int len ;
int fd;
char mes_t[MAX_CHAR];
int file_size = 0;
char file_name[SIZE_PASS_NAME];
PTHREAD_PAR * par_t = (PTHREAD_PAR *)malloc(sizeof(PTHREAD_PAR));
//解析文件大小
for(int i=0 ;i<NUM_MAX_DIGIT ;i++)
{
if(m_pack_recv_file_mes[id].data.mes[i] == -1)
break;
int t1 = 1;
for(int l=0;l<i;l++)
t1*=10;
file_size += (int)m_pack_recv_file_mes[id].data.mes[i]*t1;
}
// for(int i=0 ;i<=50;i++)
// printf("%d\n", m_pack_recv_file_mes[id].data.mes[i]);
// printf("%s\n", m_pack_recv_file_mes[id].data.mes+NUM_MAX_DIGIT);
strcpy(file_name,m_pack_recv_file_mes[id].data.mes+NUM_MAX_DIGIT);
printf("\033[;33m\33[1m %s send file %s size(%db)to you \033[0m\n", m_pack_recv_file_mes[id].data.send_name,file_name,file_size);
printf(" do you want receive it? \n");
printf("(y/n) :");
scanf("%s", choice);
if(choice[0] != 'Y' && choice[0] != 'y')
{
file_infor_delete(id);
return ;
}
//建立文件
if((fd = open(file_name,O_WRONLY | O_CREAT , S_IRUSR | S_IWUSR)) < 0)
{
my_err("open",__LINE__);
return ;
}
len = lseek(fd, 0, SEEK_END);
close(fd);
par_t->a = file_size;
par_t->b = len;
int digit = 0;
while(len != 0)
{
mes_t[digit++] = len%10;
len /= 10;
}
mes_t[digit] = -1;
//发送同意同意
send_pack_memcpy(FILE_SEND_BEGIN_RP ,m_my_infor.username ,file_name ,mes_t);
//开启线程接收文件
pthread_create(&pid_recv_file,NULL,pthread_recv_file,(void *)par_t);
file_infor_delete(id);
}
//处理接收文件中断信息,
//并询问是否继续接收
void mes_recvfile_fail(int id)
{
pthread_t pid_recv_file;
char chioce[10];
int begin_location_server;
int file_size;
char file_name[SIZE_PASS_NAME];
char mes_t[MAX_CHAR];
PTHREAD_PAR * par_t = (PTHREAD_PAR *)malloc(sizeof(PTHREAD_PAR));
//解析已经接收的字节数
for(int i=0 ;i<NUM_MAX_DIGIT ;i++)
{
if(m_pack_recv_file_mes[id].data.mes[i] == -1)
break;
int t1 = 1;
for(int l=0;l<i;l++)
t1*=10;
file_size += (int)m_pack_recv_file_mes[id].data.mes[i]*t1;
}
strcpy(file_name,m_pack_recv_file_mes[id].data.mes+NUM_MAX_DIGIT);
begin_location_server= get_file_size(file_name);
par_t->a = file_size;
par_t->b = begin_location_server;
printf("\033[;31m\33[1mthe file %s recv failed ,have recved \033[;32m%d%%\033[;31m,do you want recv continue?\033[0m\n", file_name,(int)((double)begin_location_server/file_size*100));
printf("y/n :");
scanf("%s",chioce);
if(chioce[0] != 'Y' && chioce[0] != 'y')
{
file_infor_delete(id);
return ;
}
int len = begin_location_server;
int digit = 0;
while(len != 0)
{
mes_t[digit++] = len%10;
len /= 10;
}
mes_t[digit] = -1;
//返回同意信息
send_pack_memcpy(FILE_SEND_BEGIN_RP ,m_my_infor.username ,file_name ,mes_t);
//开启线程接收文件
pthread_create(&pid_recv_file,NULL,pthread_recv_file,(void *)par_t);
file_infor_delete(id);
}
//接收文件线程,
//从存储接收包的地方检索到信息
//并写入文件
//当文件写入完成,关闭线程
void *pthread_recv_file(void *par_t)
{
PTHREAD_PAR * pthread_par = (PTHREAD_PAR * )par_t;
int file_size = pthread_par->a ;
int begin_location_server = pthread_par->b;
int sum = begin_location_server;
while(1)
{
pthread_mutex_lock(&mutex_recv_file);
int fd;
char file_name[MAX_CHAR];
for(int i=1;i<=m_recv_num_file ;i++)
{
int len = 0;
for(int j=0 ;j<NUM_MAX_DIGIT ;j++)
{
if(m_pack_recv_file[i].data.mes[j] == -1)
break;
int t1 = 1;
for(int l=0;l<j;l++)
t1*=10;
len += (int)m_pack_recv_file[i].data.mes[j]*t1;
}
strcpy(file_name,m_pack_recv_file[i].data.send_name);
//you can creat this file when you get the file_send_begin
if((fd = open(file_name,O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0)
{
my_err("open",__LINE__);
return NULL;
}
if(write(fd,m_pack_recv_file[i].data.mes + NUM_MAX_DIGIT,len) < 0)
my_err("write",__LINE__);
// 关闭文件
close(fd);
sum += len;
int color;
int jindu=(int)((double)sum/file_size*100);
printf("have recved :");
for(int i = 0 ;i<jindu/10;i++)
{
color = i%6;
printf("\033[;%dm\33[1m=\033[0m",color+32);
fflush(stdout);
}
printf("\033[;31m\33[1m>\033[0m");
fflush(stdout);
for(int j = 0;j<10-jindu/10;j++)
{
printf(" ");
fflush(stdout);
}
printf("\033[;31m\33[1m|\033[0m %d%% %d \n",jindu,sum);
m_recv_num_file = 0;
//文件接收完成,输出提示信息,跳出线程
if(sum >= file_size)
{
send_pack(FILE_FINI_RP,m_my_infor.username,"server",file_name);
printf("send finished!!\n");
print_main_menu();
return NULL;
}
}
pthread_mutex_unlock(&mutex_recv_file);
usleep(10);
}
}
//显示历史信息
//向服务端发送请求消息
int mes_record()
{
char username[MAX_CHAR];
printf("please input the username that you want see:\n");
scanf("%s",username);
printf("the recording :\n");
send_pack(MES_RECORD,m_my_infor.username,"server",username);
printf("\33[2J\33[20A\033[;33m\33[1m^-^-^-^-^-^-^-^-^message recordes^-^-^-^-^-^-^-^\033[0m\n");
while(!m_flag_print_recorde) ;
printf("printf recordes finished!!\n");
m_flag_print_recorde = 0;
return 0;
}
//输出历史消息
void print_mes_record(PACK* pack_t)
{
if(strcmp(pack_t->data.send_name , "server") == 0)
{
if(strcmp(pack_t->data.mes,m_my_infor.username) == 0)
{
printf("\033[;34m\33[1m%s\033[0m\t\033[;34m\033[0m\n",pack_t->data.mes);
printf("%s\n", pack_t->data.mes+SIZE_PASS_NAME);
}
else
{
printf("\033[;33m\33[1m%s\033[0m\t\033[;33m\033[0m\n",pack_t->data.mes);
printf("%s\n", pack_t->data.mes+SIZE_PASS_NAME);
}
}
else
m_flag_print_recorde = 1;
free(pack_t);
}
/*****************************************/
/*void print_file_mes()
{
for(int i=1 ;i<=5;i++)
{
printf("hahahahahaha*****\n");
printf("%s\n", m_pack_recv_file_mes[i].data.send_name);
printf("%s",m_pack_recv_file_mes[i].data.recv_name);
for(int j=0;j<=5;j++)
printf("%d\n\n",m_pack_recv_file_mes[i].data.mes[j]);
}
}*/
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/
tools.cpp
#include "client.h"
void my_err(const char * err_string,int line)
{
fprintf(stderr, "line:%d ", line);
perror(err_string);
exit(1);
}
void sig_close(int i)
{
//关闭客户端的描述符
close(sockfd);
exit(0);
}
/*you need creat the file before!*/
//得到文件大小
int get_file_size(char *file_name)
{
int fd;
int len;
if((fd = open(file_name,O_RDONLY)) == -1)
{
my_err("open",__LINE__);
return 0;
}
len = lseek(fd, 0, SEEK_END);
close(fd);
return len;
}
//从文件数组中删除文件信息
void file_infor_delete(int id)
{
pthread_mutex_lock(&mutex_local_user);
for(int j = id ;j <=m_recv_num_file_mes ;j++)
{
m_pack_recv_file_mes[j] = m_pack_recv_file_mes[j+1];
}
m_recv_num_file_mes--;
pthread_mutex_unlock(&mutex_local_user);
}
//判断是否有重复的组
int judge_same_group(char *group_name)
{
int i;
for(i=1;i<=m_my_infor.group_num;i++)
{
if(strcmp(m_my_infor.group[i],group_name) == 0)
return 1;
}
return 0;
}
//判断是否有重复的好友
int judge_same_friend(char add_friend_t[])
{
int i;
for(i=1;i<=m_my_infor.friends_num;i++)
{
if(strcmp(m_my_infor.friends[i].name,add_friend_t) == 0)
return i;
}
return 0;
}
//为避免输入时出现的意外错误,进行字符串解析
int get_choice(char *choice_t)
{
int choice =0;
for(int i=0;i<strlen(choice_t) ;i++)
if(choice_t[i]<'0' || choice_t[i]>'9')
return -1;
for(int i=0;i<strlen(choice_t);i++)
{
int t=1;
for(int j=1;j<strlen(choice_t)-i;j++)
{
t *=10;
}
choice += t*(int)(choice_t[i] - 48);
}
return choice;
}
//根据参数信息发送包
void send_pack(int type,char *send_name,char *recv_name,char *mes)
{
PACK pack_send_pack;
time_t timep;
pack_send_pack.type = type;
strcpy(pack_send_pack.data.send_name,send_name);
strcpy(pack_send_pack.data.recv_name,recv_name);
strcpy(pack_send_pack.data.mes,mes);
time(&timep);
//pack_send_pack.data.time = timep;
if(send(sockfd,&pack_send_pack,sizeof(PACK),0) < 0){
my_err("send",__LINE__);
}
}
//根据参数信息发送包
void send_pack_memcpy(int type,char *send_name,char *recv_name,char *mes)
{
PACK pack_send_pack;
time_t timep;
pack_send_pack.type = type;
strcpy(pack_send_pack.data.send_name,send_name);
strcpy(pack_send_pack.data.recv_name,recv_name);
memcpy(pack_send_pack.data.mes,mes,MAX_CHAR*2);
time(&timep);
// pack_send_pack.data.time = timep;
if(send(sockfd,&pack_send_pack,sizeof(PACK),0) < 0){
my_err("send",__LINE__);
}
}
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/
view.cpp
#include "client.h"
//登陆菜单
int login_menu()
{
char choice_t[100];
int chioce;
do
{
printf("\n\t\t\033[;34m\33[1m*******************************\033[0m\n");
printf("\t\t\033[;34m\33[1m*\033[0m 1.login in \033[;34m\33[1m*\033[0m \n");
printf("\t\t\033[;34m\33[1m*\033[0m 2.register \033[;34m\33[1m*\033[0m \n");
printf("\t\t\033[;34m\33[1m*\033[0m 0.exit \033[;34m\33[1m*\033[0m \n");
printf("\t\t\033[;34m\33[1m*******************************\033[0m\n");
printf("\t\tchoice:");
scanf("%s",choice_t);
chioce = get_choice(choice_t);
switch(chioce)
{
case 1:
if(login() == 1)
return 1;
break;
case 2:
registe();
break;
default:
break;
}
}while(chioce!=0);
return 0;
}
//显示聊天信息
void show_mes_smart(char *name ,char *mes)
{
time_t timep;
int number = 6;
char time1[100];
int len ;
time (&timep);
strcpy(time1,ctime(&timep));
len = strlen(time1);
time1[len-5] = '\0';
if(m_print_mes_num == number)
{
for(int i=1;i<=5 ;i++)
m_print_mes[i] = m_print_mes[i+1];
strcpy(m_print_mes[number].name,name);
// strcpy(m_print_mes[number].time,time);
strcpy(m_print_mes[number].mes,mes);
}
else{
strcpy(m_print_mes[++m_print_mes_num].name,name);
//strcpy(m_print_mes[m_print_mes_num].time,time);
strcpy(m_print_mes[m_print_mes_num].mes,mes);
}
printf("\33[s");
fflush(stdout);
printf("\33[25A\n");
for(int i=1;i<=20;i++)
printf("\33[K\n");
printf("\33[21A\n");
for(int i=1;i<=m_print_mes_num;i++)
{
if(strcmp(m_print_mes[i].name,m_my_infor.username) == 0)
{
printf("\033[;34m\33[1m%s\033[0m\t\033[;34m%s\033[0m\n",m_print_mes[i].name,time1+10);
printf("%s\n", m_print_mes[i].mes);
}
else
{
printf("\033[;33m\33[1m%s\033[0m\t\033[;33m%s\033[0m\n",m_print_mes[i].name,time1+10);
printf("%s\n", m_print_mes[i].mes);
}
}
for(int i=1;i<=6- m_print_mes_num ;i++)
{
printf("\n");
printf("\n\n");
}
printf("\33[u");
fflush(stdout);
}
//好友列表查看
void friends_see()
{
pthread_mutex_lock(&mutex_local_user);
printf("\33[2J\n");
printf("\33[1;1H\n");
printf("\033[;35m\33[1m\t ***********the list of friends************* \033[0m \n");
for(int i=1 ;i<=m_my_infor.friends_num ;i++)
{
switch(m_my_infor.friends[i].statu)
{
case ONLINE:
printf("\033[;35m\33[1m\t ID[%d]: \033[0m \033[;32m\33[1m%s\033[0m [ONLINE] ", i,m_my_infor.friends[i].name);
if(m_my_infor.friends[i].mes_num)
printf("\033[;33m%d messages\033[0m\n", m_my_infor.friends[i].mes_num);
else
printf("\n");
break;
case DOWNLINE:
printf("\033[;35m\33[1m\t ID[%d]: \033[0m \033[;31m\33[1m%s\033[0m [DOWNLINE] ", i,m_my_infor.friends[i].name);
if(m_my_infor.friends[i].mes_num)
printf("\033[;33m%d messages\033[0m\n", m_my_infor.friends[i].mes_num);
else
printf("\n");
break;
}
}
printf("\n\n");
printf("\033[;35m\33[1m\t *******************end********************* \033[0m \n");
pthread_mutex_unlock(&mutex_local_user);
}
//群组信息查看
void group_see()
{
pthread_mutex_lock(&mutex_local_user);
printf("\33[2J\n");
printf("\33[1;1H\n");
printf("\033[;35m\33[1m\t ***********the list of groups************* \033[0m \n");
for(int i=1 ;i<=m_my_infor.group_num ;i++)
{
printf("\033[;35m\33[1m\t ID[%d]: \033[0m \033[;32m\33[1m%s\033[0m", i,m_my_infor.group[i]);
}
printf("\n\n");
printf("\033[;35m\33[1m\t ********************end******************* \033[0m \n");
pthread_mutex_unlock(&mutex_local_user);
}
void print_main_menu()
{
printf("\n\t\t\033[;34m\33[1m*********************************\033[0m \n");
printf("\t\t\033[;34m\33[1m*\033[0m 1.show friends \033[;34m\33[1m*\033[0m\n");
printf("\t\t* 2.add friends *\n");
printf("\t\t\033[;34m\33[1m*\033[0m 3.delete friends \033[;34m\33[1m*\033[0m\n");
printf("\t\t\033[;34m\33[1m*\033[0m 4.show group \033[;34m\33[1m*\033[0m\n");
printf("\t\t* 5.create group *\n");
printf("\t\t\033[;34m\33[1m*\033[0m 6.join group \033[;34m\33[1m*\033[0m\n");
printf("\t\t\033[;34m\33[1m*\033[0m 7.quit group \033[;34m\33[1m*\033[0m\n");
printf("\t\t* 8.delete group *\n");
printf("\t\t\033[;34m\33[1m*\033[0m 9.chat with one \033[;34m\33[1m*\033[0m\n");
printf("\t\t\033[;34m\33[1m*\033[0m 10.chat with many \033[;34m\33[1m*\033[0m\n");
printf("\t\t* 11.send file *\n");
printf("\t\t\033[;34m\33[1m*\033[0m 12.file message box %d \033[;34m\33[1m*\033[0m\n",m_recv_num_file_mes);
printf("\t\t\033[;34m\33[1m*\033[0m 13.mes recording \033[;34m\33[1m*\033[0m\n");
printf("\t\t\033[;34m\33[1m*\033[0m 0.exit \033[;34m\33[1m*\033[0m\n");
printf("\t\t\033[;34m\33[1m*********************************\033[0m\n");
printf("\t\tchoice:");
}
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/
client.cpp
#include <mysql/mysql.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <termios.h>
/*****************same with server**********************/
#define LOGIN 1
#define REGISTER 2
#define FRIEND_SEE 3
#define FRIEND_ADD 4
#define FRIEND_DEL 5
#define GROUP_SEE 6
#define GROUP_CREATE 7
#define GROUP_JOIN 8
#define GROUP_QIUT 9
#define GROUP_DEL 10
#define CHAT_ONE 11
#define CHAT_MANY 12
#define FILE_SEND_BEGIN 13
#define FILE_SEND_BEGIN_RP 14
#define FILE_SEND_STOP_RP 15
#define FILE_RECV_RE 16
#define FILE_SEND 17
#define FILE_RECV_BEGIN 18
#define FILE_RECV_BEGIN_RP 19
#define FILE_RECV_STOP_RP 20
#define FILE_RECV 21
#define FILE_FINI_RP 22
#define MES_RECORD 23
#define EXIT -1
#define SIZE_PASS_NAME 10
#define MAX_PACK_CONTIAN 100
#define MAX_CHAR 300
#define NUM_MAX_DIGIT 10
#define DOWNLINE 0
#define ONLINE 1
#define BUZY 2
/**************************************************/
typedef struct friend_info
{
int statu;
int mes_num;
char name[MAX_CHAR];
}FRIEND_INFO;
typedef struct user_infor{
char username [MAX_CHAR];
FRIEND_INFO friends [MAX_CHAR];
int friends_num;
char group [MAX_CHAR][MAX_CHAR];
int group_num;
}USER_INFOR;
/******************be sure same with server*******************************/
typedef struct datas{
char send_name[MAX_CHAR];
char recv_name[MAX_CHAR];
int send_fd;
int recv_fd;
//time_t time;
char mes[MAX_CHAR*2];
}DATA;
typedef struct package{
int type;
DATA data;
}PACK;
typedef struct pthread_parameter
{
int a;
int b;
}PTHREAD_PAR;
typedef struct prinit_mes
{
char name[MAX_CHAR];
char time[MAX_CHAR];
char mes [MAX_CHAR];
}PRINT_MES;
typedef struct sockaddr SA;
void init();
void *deal_statu(void *arg);
void *clien_recv_thread(void *arg);
void init_clien_pthread();
int main_menu();
int send_login(char username_t[],char password_t[]);
int login();
int send_registe(char username_t[],char password_t[]);
void registe();
void get_status_mes();
void change_statu(PACK pack_deal_statu_t);
void add_friend();
void del_friend();
void group_create();
void group_join();
void group_qiut();
void group_del();
void send_mes_to_one();
void send_mes_to_group();
void send_mes(char mes_recv_name[],int type);
void *show_mes(void *username);
void print_mes(int id);
void send_file();
void *pthread_send_file(void *mes_t);
void send_file_send(int begin_location,char *file_path);
int file_mes_box();
void deal_file_mes(int id);
void mes_sendfile_fail(int id);
void mes_recv_requir(int id);
void mes_recvfile_fail(int id);
void *pthread_recv_file(void *par_t);
int mes_record();
void print_mes_record(PACK* pack_t);
int login_menu();
void show_mes_smart(char *name ,char *mes);
void friends_see();
void group_see();
void print_main_menu();
void my_err(const char * err_string,int line);
void sig_close(int i);
int get_file_size(char *file_name);
void file_infor_delete(int id);
int judge_same_group(char *group_name);
int judge_same_friend(char add_friend_t[]);
int get_choice(char *choice_t);
void send_pack(int type,char *send_name,char *recv_name,char *mes);
void send_pack_memcpy(int type,char *send_name,char *recv_name,char *mes);
extern USER_INFOR m_my_infor;
extern PACK m_pack_send [MAX_CHAR];
extern int m_send_num;
/*****************recv*********************/
extern PACK m_pack_recv_friend_see [MAX_PACK_CONTIAN];
extern PACK m_pack_recv_chat [MAX_PACK_CONTIAN];
extern PACK m_pack_recv_send_file [MAX_PACK_CONTIAN];
extern PACK m_pack_recv_file_mes [MAX_PACK_CONTIAN];
extern PACK m_pack_recv_file [MAX_PACK_CONTIAN];
extern int m_recv_num_friend_see;
extern int m_recv_num_chat;
extern int m_recv_num_send_file;
extern int m_recv_num_file_mes;
extern int m_recv_num_file;
extern int m_print_mes_flag;
/****************************************************/
extern int m_flag_group_create;
extern int m_flag_group_join ;
extern int m_flag_group_del ;
extern int m_flag_print_mes;
extern int m_flag_print_recorde;
// int window_col;
// int window_row;
/****************************************************/
extern PRINT_MES m_print_mes[10];
extern int m_print_mes_num;
/***********************function***********************/
extern int sockfd;
extern char *IP ;
extern short PORT ;
extern pthread_mutex_t mutex_local_user;
extern pthread_mutex_t mutex_recv_file;
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/
Makefile
CC=g++ -std=c++11
OBJ = happychat_client
all:
$(CC) -o $(OBJ) -cpp ./*.cpp `pkg-config --libs --cflags gtk+-2.0` -pthread -g
# $(CC) -o $(OBJ) ./*.o -I `pkg-config --libs --cflags gtk+-2.0` -pthread -g
# rm -rf *.o
clean:
-rm -rf *.o
/^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/