明明聊天室是要在暑假两个星期内写完的,由于疫情没有回校学习,在家也是写一点放松一点,并且第一次写一个比较大的项目有点力不从心,总之有遗憾吧,在网络编程这块学习也是浅上折纸,在想整体架构上有明显不足,所以导致了第一版问题比较多,在垂头丧气了几天感觉自己目前能力解决不了的情况下选择了重写,过程比较痛苦,也焦虑了几夜,躺着也难受想放弃,不知道选这个有没有错,还是说自学并没有什么作用,菜是菜了点,好歹挺过来了。。。然后又是测试,学长帮我测了四次来慢慢解决一些逻辑漏洞,逐渐也熟悉了这部分的要求,再看看别人的实现和对网络编程的理解,有羡慕,也有难过,逃避宣泄着情绪,小城无路可逃。我先看到了这里,然后感受非常复杂。
该程序仅在本机上测试通过,部署到公网上时出现的getch()回显问题以及登录不上一些问题(这个可以重启client端完成登录),应该是加锁和数据阻塞的原因,由于不想改了如果有大佬看到这篇博客希望能给一些建议和帮助
我的ubuntu的版本
Linux version 5.4.0-42-generic (buildd@lgw01-amd64-038) linux内核版本号
gcc version 9.3.0 gcc编译器版本号
Ubuntu 9.3.0-10ubuntu2 Ubuntu版本号
- 加好友和加群
一般客户端发送一个请求消息给服务器后,服务器再发给客户端一个添加消息,客户端用盒子链表来存,再输入同意与否,处理一条删除一条,最后发送回执给服务器,服务器判断是否同意再发回客户端显示消息 - 离线私聊和群聊
私聊要判断有没有屏蔽,是否是好友,在不在线,不在线采用离线status位存发送与否先存mysql库里面,等对面上线了由服务器发送消息,群聊多加了是否是存在群和是否是群成员判断,以及查找发送给其他群成员的mysql查找 - 文件传输
由于实现的框架局限,这部分之前版本有些内存泄漏和栈溢出的问题,之后查到了sendfile和splice的Linux零拷贝方法,但是在参考后还是选择了上传服务器和客户端再下载的实现,注意传输的数据要完全最后要加一个消息通知服务器传输完成 - 如果不太明白一些具体逻辑的实现可以私聊我,后面看时间会不会写一个解释博客,估计是不会了
以下是代码实现
server.c
#include "chat.h"
#define EPOLLEVENT 1024
#define BUFMAX 1024
#define BUF 2048
char *Server_time();
int Set_no_block(int sfd);
int sys_log;
MYSQL mysql;
/*
void Add_node(int fd,int id,char* name);
void Send_register_pack(int fd,int flag,char* buf,int id);
int Get_status(int id);
char* Get_name(int id);*/
int main()
{
/*if((sys_log=open("sys_log",O_WRONLY | O_CREAT | O_APPEND,S_IRUSR|S_IWUSR))<0)
{
sys_err("open error",__LINE__);
return 0;
}
dup2(sys_log,1);*/
signal(SIGINT,Signal_close);
//pthread_mutex_init(&mutex,NULL);
//pthread_cond_init(&cond,NULL);
Connect_mysql();
/*printf("线程池启动\n");
pool_init(MAX_THREAD_NUM);
printf("线程池启动成功!\n");
sleep(2);*/
pool_init(50);
//sleep(2);
//Read_from_mysql();
Init_socket();
//threadpool_destroy();
}
void Signal_close(int i)
{
close(sys_log);
Close_mysql(mysql);
printf("服务器关闭\n");
exit(1);
}
char *Server_time()
{
time_t ctime;//服务器时间
struct tm *server_time;
time(&ctime);
server_time=localtime(&ctime);
return asctime(server_time);
}
int Set_no_block(int sfd)
{
/* 内层调用fcntl()的F_GETFL获取flag,
* 外层fcntl()将获取到的flag设置为O_NONBLOCK非阻塞*/
if( fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) ) == -1)
{
return -1;
}
return 0;
}
void Init_socket(int argc,char *argv[])
{
struct stat stat_buf;
const char* file_name=argv[1];
int file_fd=open(file_name,O_RDONLY);
fstat(file_fd,&stat_buf);
close(file_fd);
List_Init(list_ser,server_user_node_t);
printf("服务端启动\n");
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len;
lfd=Socket(AF_INET,SOCK_STREAM,0);
Set_no_block(lfd);
//端口复用
int opt=1;
setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERV_PORT);
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
Listen(lfd,128);
printf("服务器启动成功!\n");
epfd=epoll_create(EPOLLEVENT);
struct epoll_event tep,ep[EPOLLEVENT];
tep.events=EPOLLIN;
tep.data.fd=lfd;
epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&tep);
int i;
int ret;
pthread_t pid;
char buf[BUFMAX];
//memset(buf,0,sizeof(buf));
while(1)
{
ret=epoll_wait(epfd,ep,EPOLLEVENT,-1);
for(i=0;i<ret;i++)
{
//printf("the event is %x\n",ep[i].events);
int fd=ep[i].data.fd;
if (!(ep[i].events & EPOLLIN)) //如果不是"读"事件, 继续循环
continue;
if(ep[i].data.fd==lfd)
{
cli_addr_len=sizeof(cli_addr);
cfd=Accept(lfd,(struct sockaddr*)&cli_addr,&cli_addr_len);
printf("连接到新的客户端ip:%s\n端口号:%d\n",inet_ntoa(cli_addr.sin_addr),cli_addr.sin_port);
/*设置非阻塞io*/
if(Set_no_block(cfd) != 0 )
{
printf("SET_no_black\n");
printf("%s",Server_time());
close(cfd);
continue;
}
tep.events=EPOLLIN;
tep.data.fd=cfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&tep)<0)
{
printf("EPOLL_CTL add client error\n");
printf("%s",Server_time());
close(cfd);
continue;
}
}
/*else if(ep[i].events & EPOLLOUT)
{
printf("start to sendfile !\n");
printf("处理写事件\n");
int write;
write=send(fd,buf,strlen(buf),0);
if(write == -1)
{
my_err("write event error",__LINE__);
close(fd);
}
else
{
printf("发送消息成功\n");
}
memset(buf,0,BUFMAX);
}*/
/*else if(ep[i].events & EPOLLOUT)
{
printf("start to sendfile !\n");
int send_ret=0;
int left=stat_buf.st_size;
file_fd=open(file_name,O_RDONLY);
while(left>0)
{
send_ret=sendfile(cfd,file_fd,NULL,BUF);
if(send_ret<0 && errno==EAGAIN)
{
continue;
}
else if(send_ret==0)
{
break;
}
else
{
left-=send_ret;
}
}
printf("sendfile over !\n");
close(file_fd);
tep.data.fd=cfd;
epoll_ctl(epfd,EPOLL_CTL_DEL,cfd,&tep);
close(cfd);
}*/
else if(ep[i].events & EPOLLIN)
{
memset(buf,0,sizeof(buf));
int n=recv(ep[i].data.fd,buf,sizeof(buf),MSG_WAITALL);
int fd=ep[i].data.fd;
printf("\n");
/*printf("%d\n",recv_t.data.send_fd);
printf("%d\n",recv_t.data.recv_fd);
printf("server message%s\n",recv_t.data.message);
printf("server recv:%s\n",recv_t.data.send_name);*/
if(n<0)
{
close(ep[i].data.fd);
sys_err("recv error!",__LINE__);
continue;
}
else if(n==0)
{
printf("??????\n");
server_list_t pos;
List_ForEach(list_ser,pos)
{
if(pos->data.connfd==ep[i].data.fd)
{
printf("sssssssssssss\n");
char buf_t[BUFSIZ];
sprintf(buf_t,"update account set status=0 where id=%d",pos->data.id);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
//printf("用户[%d]已经下线\n",pos->data.id);
printf("账号[%d]下线了:%d\n",pos->data.id,pos->data.connfd);
List_FreeNode(pos);
break;
}
}
tep.data.fd=ep[i].data.fd;
printf("客户端:%d连接断开\n",tep.data.fd);
epoll_ctl(epfd,EPOLL_CTL_DEL,ep[i].data.fd,&tep);
close(ep[i].data.fd);
continue;
}
int flag;
memcpy(&flag,buf,sizeof(int));
printf("flag:%d\n",flag);
switch(flag)
{
case LOGIN:
Login(fd,buf);
break;
case REGISTER:
Register(fd,buf);
break;
case EXIT:
Exit(fd,buf);
break;
case ADD_FRIEND:
Add_friend(fd,buf);
break;
case ADD_FRIEND_ACCEPT:
Add_friend_accept(fd,buf);
break;
case DEL_FRIEND:
Del_friend(fd,buf);
break;
case PRIVATE_CHAT:
Private_chat(fd,buf);
break;
//写在一起比较好
//case SHOW_FRIEND_STATUS:
case VIEW_FRIEND_LIST:
View_friend_list(fd,buf);
break;
case SHIELD:
Shield_friend(fd,buf);
break;
case UNSHIELD:
Unshield_friend(fd,buf);
break;
case VIEW_CHAT_HISTORY:
View_chat_history(fd,buf);
break;
case CREAT_GROUP:
Create_group(fd,buf);
break;
case ADD_GROUP:
Add_group(fd,buf);
break;
case ADD_GROUP_ACCEPT:
Add_group_accept(fd,buf);
break;
case WITHDRAW_GROUP:
Withdraw_group(fd,buf);
break;
//一起实现
case VIEW_GROUP_MEMBER:
View_group_member(fd,buf);
break;
case VIEW_ADD_GROUP:
View_add_group(fd,buf);
break;
case SET_GROUP_ADMIN:
Set_group_admin(fd,buf);
break;
case KICK:
Kick(fd,buf);
break;
case GROUP_CHAT:
Group_chat(fd,buf);
break;
case VIEW_GROUP_RECORD:
View_group_record(fd,buf);
break;
/*case SEND_FILE:
printf("here\n");
{
printf("111111111111111\n");
char *buf1=(char*)malloc(sizeof(1024));
printf("22222222222222222\n");
memcpy(buf1,buf,sizeof(file_t));
printf("333333333333333333\n");
threadpool_add(Send_file,(void*)buf1);*/
/*printf("....\n");
file_t file;
char *str=(char*)malloc(sizeof(file));
memcpy(str,buf,sizeof(file));
pthread_t recv_file_id;
pthread_create(&recv_file_id,NULL,Send_file,(void*)str);
printf(">>>>\n");*/
//Send_file(fd,buf);
//break;
//}
case SEND_FILE:
break;
case UPLOAD:
Upload(fd,buf);
break;;
/*case RECV_FILE:
//Recv_file(fd,buf);
break;*/
case DOWNLOAD:
Download(fd,buf);
break;
case 0:
break;
}
}
}
}
close(epfd);
close(lfd);
}
void Register(int fd,char* buf)
{
Account_t account;
memcpy(&account,buf,sizeof(account));
printf("server name:%s\n",account.name);
printf("server password:%s\n",account.password);
server_user_t user;
strcpy(user.name,account.name);
strcpy(user.password,account.password);
printf("server username:%s\n",user.name);
printf("server password:%s\n",user.password);
account.online=DOWNLINE;
char buf_t[BUFSIZ];
sprintf(buf_t,"insert into account values(NULL,'%s','%s','%d')",account.name,account.password,account.online);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
printf("注册失败\n");
/*char mes[256];
sprintf(mes,"你输入的名称[%s]有误,请重新输入",account.name);
Send_pack(fd,REGISTER_ERROR_APPLY,mes);*/
}
else
printf("注册成功\n");
memset(buf_t,0,sizeof(buf_t));
sprintf(buf_t,"select LAST_INSERT_ID()");
printf("buf_t:%s\n",buf_t);
ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
row=mysql_fetch_row(result);
int id=atoi(row[0]);
printf("server username:%d",id);
char str[256];
//strcpy(str,account.username);
sprintf(str,"账号[%d]注册成功",id);
Send_register_pack(fd,REGISTER_APPLY,str,id);
printf("666666666\n");
}
void Send_register_pack(int fd,int flag,char* buf,int id)
{
char str[BUFSIZ];
message mes;
mes.flag=flag;
mes.id=id;
strcpy(mes.message,buf);
printf("server send message:%s\n",mes.message);
memcpy(str,&mes,sizeof(mes));
printf("server send id:%d\n",mes.id);
printf("server send flag:%d\n",mes.flag);
if(send(fd,str,sizeof(str),0)<0)
{
my_err("send error!",__LINE__);
close(fd);
}
}
void Login(int fd,char* buf)
{
Account_t account;
memcpy(&account,buf,sizeof(account));
printf("server id:%d\n",account.id);
printf("server password:%s\n",account.password);
char name[MAX];
int send_fd=Get_connfd(account.id);
/*server_list_t pos;
List_ForEach(list_ser,pos)
{
if(pos->data.id==account.id)
{
send_fd=pos->data.connfd;
}
}*/
if(send_fd>0)
{
printf("账号已登录\n");
Send_pack(fd,LOGIN_APPLY,"a");
return ;
}
char buf_t[BUFSIZ];
sprintf(buf_t,"select *from account where id=%d",account.id);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
row=mysql_fetch_row(result);
//printf("row[0]:%s\n",row[0]);
if(row==NULL)
{
printf("/\n");
/*char mes[256];
sprintf(mes,"密码错误或者账号不存在!\n");
Send_pack(fd,LOGIN_APPLY,mes);*/
Send_pack(fd,LOGIN_APPLY,"n");
return ;
}
else
{
printf("row[0]:%s\n",row[0]);
//if(strcmp(row[0],user.username)==0)
//{
// memset(buf_t,0,sizeof(buf_t));
//sprintf(buf_t,"select username from account");
//printf("buf_t:%s\n",buf_t);
strcpy(name,row[1]);
printf("name:%s\n",row[1]);
if(strcmp(row[2],account.password)==0)
{
Add_node(fd,account.id,name);
server_list_t p;
List_ForEach(list_ser,p)
{
printf("username:%d\n",p->data.id);
printf("connfd:%d\n",p->data.connfd);
printf("name:%s\n",p->data.name);
}
Send_pack(fd,LOGIN_APPLY,"y");
memset(buf_t,0,sizeof(buf_t));
sprintf(buf_t,"update account set status=1 where id=%d",account.id);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("[%d]登录成功\n",account.id);
Send_offline_apply(fd,account.id);
Send_offline_messgae(fd,account.id);
}
else
Send_pack(fd,LOGIN_APPLY,"n");
//}
}
}
void Send_offline_apply(int fd,int recver)
{
char buf[BUFSIZ];
sprintf(buf,"select *from friend where (fid=%d and request=%d)",recver,0);
printf("buf=%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
printf("您暂无离线好友申请消息\n");
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
while((row=mysql_fetch_row(result)))
{
char buf[BUFSIZ];
sprintf(buf,"update friend set request=2 where fid=%d",atoi(row[1]));
printf("buf=%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
char mes[256];
int requester=atoi(row[0]);
sprintf(mes,"用户[%d]请求加你为好友",requester);
Send_connfd_pack(ADD_FRIEND_APPLY,requester,recver,mes);
printf("[%d]对好友[%d]好友申请发送成功\n",requester,recver);
}
memset(buf,0,sizeof(buf));
sprintf(buf,"select sid from group_request where (mid=%d and request=2)",recver);
printf("buf=%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result2;
MYSQL_ROW row2;
result2=mysql_store_result(&mysql);
//row2=mysql_fetch_row(result2);
while((row2=mysql_fetch_row(result2)))
{
printf("row2[0]:%d\n",atoi(row2[0]));
char buf[BUFSIZ];
char mes[256];
int requester=atoi(row2[0]);
sprintf(mes,"用户[%d]请求加入群聊",atoi(row2[0]));
Send_connfd_pack(ADD_GROUP_APPLY,requester,recver,mes);
printf("[%d]对群管理[%d]的群申请发送成功\n",requester,recver);
sprintf(buf,"update group_member set request=1 where mid=%d",atoi(row2[0]));
printf("buf:%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
memset(buf,0,sizeof(buf));
sprintf(buf,"update group_request set request=1 where mid=%d",recver);
printf("buf:%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
}
}
void Send_offline_messgae(int fd,int recver)
{
char buf[BUFSIZ];
memset(buf,0,sizeof(buf));
sprintf(buf,"select *from chat_message where (fid=%d and status=%d)",recver,0);
printf("buf=%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
while((row=mysql_fetch_row(result)))
{
char str[BUFSIZ];
sprintf(str,"select *from account where id=%d",atoi(row[0]));
printf("str:%s\n",str);
int ret=mysql_real_query(&mysql,str,strlen(str));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result1;
MYSQL_ROW row1;
result1=mysql_store_result(&mysql);
row1=mysql_fetch_row(result1);
char name[MAX];
strcpy(name,row1[1]);
char buf[BUFSIZ];
sprintf(buf,"update chat_message set status=2 where fid=%d",recver);
printf("buf=%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
Chat_message mes_t;
mes_t.flag=PRIVATE_CHAT_APPLY;
mes_t.sender=atoi(row[0]);
mes_t.recver=atoi(row[1]);
strcpy(mes_t.message,row[2]);
/*char str[BUFSIZ];
memcpy(str,&mes_t,sizeof(mes_t));
if(send(fd,buf,sizeof(buf),0)<0)
{
my_err("send error!",__LINE__);
}*/
char mes[256];
sprintf(mes,"\033[;33m\33[1m%d\t\033[;32m\33[1m%s\t\033[;31m\33[1m%s\033[0m",mes_t.sender,name,mes_t.message);
Send_pack(fd,PRIVATE_CHAT_APPLY,mes);
printf("[%d]有对[%d]的离线聊天\n",mes_t.sender,mes_t.recver);
}
memset(buf,0,sizeof(buf));
sprintf(buf,"select *from group_message where (recv_name=%d and status=0)",recver);
printf("buf=%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result1;
MYSQL_ROW row1;
result1=mysql_store_result(&mysql);
while((row1=mysql_fetch_row(result1)))
{
char str[BUFSIZ];
sprintf(str,"select *from account where id=%d",atoi(row1[0]));
printf("str:%s\n",str);
int ret=mysql_real_query(&mysql,str,strlen(str));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result2;
MYSQL_ROW row2;
result2=mysql_store_result(&mysql);
row2=mysql_fetch_row(result2);
char name[MAX];
strcpy(name,row2[1]);
Chat_message mes_t;
mes_t.flag=GROUP_CHAT_APPLY;
mes_t.sender=atoi(row1[0]);
mes_t.recver=atoi(row1[1]);
strcpy(mes_t.message,row1[2]);
/*char str[BUFSIZ];
memcpy(str,&mes_t,sizeof(mes_t));
if(send(fd,buf,sizeof(buf),0)<0)
{
my_err("send error!",__LINE__);
}*/
char mes[256];
sprintf(mes,"[%d]\t%s\t%s",mes_t.sender,name,mes_t.message);
Send_pack(fd,GROUP_CHAT_APPLY,mes);
printf("[%d]有对群的离线聊天\n",mes_t.sender);
char buf[BUFSIZ];
sprintf(buf,"update group_message set status=1 where recv_name=%d",recver);
printf("buf=%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
}
}
void Exit(int fd,char* buf)
{
message mes;
memcpy(&mes,buf,sizeof(mes));
printf("server recv message:%s\n",mes.message);
char buf_t[BUFSIZ];
sprintf(buf_t,"update account set status=0 where id=%d",mes.id);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("用户[%d]已经下线\n",mes.id);
//char mes1[256];
//sprintf(mes1,"您[%d]已退出",mes.id);
//Send_pack(fd,EXIT_APPLY,mes1);
}
void Add_node(int fd,int id,char* name)
{
server_list_t pos=(server_list_t)malloc(sizeof(server_user_node_t));
pos->data.connfd=fd;
pos->data.id=id;
strcpy(pos->data.name,name);
printf("pos->data.connfd:%d\n",pos->data.connfd);
printf("pos->data.id=%d\n",pos->data.id);
printf("pos->data.name=%s\n",pos->data.name);
List_AddTail(list_ser,pos);
}
void Add_friend(int fd,char* buf)
{
Relation_t relation;
memcpy(&relation,buf,sizeof(relation));
printf("server/ friend send:%d\n",relation.send);
printf("server/ friend recv:%d\n",relation.recv);
printf("server/ friend message:%s\n",relation.message);
char buf_t[BUFSIZ];
//查询有没有这两个人的账号
sprintf(buf_t,"select request from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
row=mysql_fetch_row(result);
//获得申请者的客户端套接字
int send_fd;
send_fd=Get_connfd(relation.send);
//如果没有这两个的信息
if(row==NULL)
{
//查看添加好友账户是否存在
char buf[BUFSIZ];
sprintf(buf,"select status from account where id=%d",relation.recv);
printf("buf:%s\n",buf);
ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result1;
MYSQL_ROW row1;
result1=mysql_store_result(&mysql);
row1=mysql_fetch_row(result1);
if(row1==NULL)
{
char mes[256];
sprintf(mes,"账号[%d]不存在",relation.recv);
Send_pack(send_fd,PRINT_APPLY,mes);
return;
}
//用户存在
relation.relation=STRANGER;
memset(buf_t,0,sizeof(buf_t));
//请求为0
//表示好友还没验证
sprintf(buf_t,"insert into friend values('%d','%d','%d','%d')",relation.send,relation.recv,relation.relation,0);
printf("buf_t:%s\n",buf_t);
ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("用户%d对%d发起了好友申请\n",relation.send,relation.recv);
//获得被申请好友的客户端套接字
//如果在线
int recv_fd=Get_connfd(relation.recv);
printf("hehehheheheh>>>>>>>>>\n");
printf("recv_fd:%d\n",recv_fd);
if(recv_fd<0)
{
printf("所申请的用户[%d]不在线\n",relation.recv);
Send_pack(send_fd,PRINT_APPLY,"d");
return;
}
else
{
char str[256];
sprintf(str,"用户[%d]向你发送了好友请求",relation.send);
Send_connfd_pack(ADD_FRIEND_APPLY,relation.send,relation.recv,str);
//如果在线为request为2已经发送
char buf[BUFSIZ];
sprintf(buf,"update friend set request=2 where (uid=%d and fid=%d)",relation.send,relation.recv);
printf("buf=%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
}
}
else if(row!=NULL)
{
if(atoi(row[0])==0)
{
char mes[256];
sprintf(mes,"正在等待对方验证,请不要重复发好友申请");
Send_pack(send_fd,PRINT_APPLY,mes);
return;
}
if(atoi(row[0])==2)
{
char mes[256];
sprintf(mes,"请勿重复添加好友");
Send_pack(send_fd,PRINT_APPLY,mes);
return;
}
}
}
/*void Add_friend(int fd,char* buf)
{
Relation_t relation;
memcpy(&relation,buf,sizeof(relation));
printf("server/ friend send:%d\n",relation.send);
printf("server/ friend recv:%d\n",relation.recv);
printf("server/ friend message:%s\n",relation.message);
char buf_t[BUFSIZ];
//查询有没有这两个人的账号
sprintf(buf_t,"select *from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
printf("buf_t:%s\n",buf_t);
int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
MYSQL_RES *result;
MYSQL_ROW row;
result=mysql_store_result(&mysql);
row=mysql_fetch_row(result);
//获得申请者的客户端套接字
int send_fd;
send_fd=Get_connfd(relation.send);
//如果没有这两个的信息
if(row==NULL)
{
//
relation.relation=STRANGER;
memset(buf_t,0,sizeof(buf_t));
sprintf(buf_t,"insert into friend values('%d','%d','%d','%d')",relation.send,relation.recv,relation.relation,0);
printf("buf_t:%s\n",buf_t);
ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("用户%d对%d发起了好友申请\n",relation.send,relation.recv);
//获得被申请好友的客户端套接字
//如果在线
int recv_fd=Get_connfd(relation.recv);
printf("hehehheheheh>>>>>>>>>\n");
printf("recv_fd:%d\n",recv_fd);
if(recv_fd<0)
{
printf("所申请的用户[%d]不在线\n",relation.recv);
Send_pack(send_fd,PRINT_APPLY,"d");
return;
}
else
{
char str[256];
sprintf(str,"用户[%d]向你发送了好友请求",relation.send);
Send_connfd_pack(ADD_FRIEND_APPLY,relation.send,relation.recv,str);
//如果在线为request为2已经发送
char buf[BUFSIZ];
sprintf(buf,"update friend set request=2 where (uid=%d and fid=%d)",relation.send,relation.recv);
printf("buf=%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
}
}
else if(row!=NULL)
{
Send_pack(send_fd,PRINT_APPLY,"w");
return;
}
}*/
void Send_connfd_pack(int flag,int sender,int recver,char* buf)
{
int recv_fd;
server_list_t pos;
//获得接受者套接字
List_ForEach(list_ser,pos)
{
if(pos->data.id==recver)
{
printf("该用户的客户端套接字为:%d\n",pos->data.connfd);
recv_fd=pos->data.connfd;
}
}
int send_fd;
send_fd=Get_connfd(sender);
char str[BUFSIZ];
box_t box;
box.flag=flag;
box.sender=sender;//申请者
box.recver=recver;//被申请者
box.send_fd=send_fd;//申请者客户端号
box.recv_fd=recv_fd;//被申请者客户端号
//buf:用户[%d]向你发送了好友请求
strcpy(box.message,buf);
memcpy(str,&box,sizeof(box));
printf("server send message:%s\n",box.message);
printf("server send flag:%d\n",box.flag);
printf("server/ friend send id:%d\n",box.sender);
printf("server/ friend recv id:%d\n",box.recver);
//朋友客户端号
printf("server/ friend recv_fd:%d\n",recv_fd);
printf("server/ friend send_fd:%d\n",send_fd);
if(send(recv_fd,str,sizeof(str),0)<0)
{
my_err("send error!",__LINE__);
}
}
void Add_friend_accept(int fd,char* buf)
{
Relation_t relation;
memcpy(&relation,buf,sizeof(relation));
printf("server/ friend accpet send:%d\n",relation.send);
printf("server/ friend accpet recv:%d\n",relation.recv);
printf("server/ friend accpet message:%s\n",relation.message);
char str1[BUFSIZ];
char str2[BUFSIZ];
if(strcmp(relation.message,"y")==0)
{
char buf[BUFSIZ];
relation.relation=PAL;
sprintf(buf,"update friend set status =%d where (uid=%d and fid=%d) ",relation.relation,relation.recv,relation.send);
printf("buf:%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("[%d]成为了[%d]的新朋友\n",relation.send,relation.recv);
sprintf(str1,"[%d]通过了您的好友请求",relation.send);
Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
sprintf(str2,"你已经和[%d]成为了朋友",relation.recv);
Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.recv,relation.send,str2);//发给被申请者
}
else
{
char buf[BUFSIZ];
sprintf(buf,"delete from friend where (uid=%d and fid=%d)",relation.recv,relation.send);
printf("buf:%s\n",buf);
int ret=mysql_real_query(&mysql,buf,strlen(buf));
if(ret)
{
Mysql_with_error(&mysql);
}
printf("[%d]拒绝成为[%d]的好友\n",relation.send,relation.recv);
memset(str1,0,sizeof(str1));
sprintf(str1,"[%d]拒绝了您的好友请求",relation.send);
Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
}
}
void Send_pack_name(int flag ,int sender,int recver,char *buf)
{
int recv_fd=Get_connfd(recver);
char str[BUFSIZ];
apply_messgae mes;
mes.flag=flag;
mes.sender=sender;//被申请者
mes.recver=recver;//申请者
strcpy(mes.message,buf);
printf("server/ friend accept apply send:%d\n",mes.sender);
printf("server/ friend accept apply recv:%d\n",mes.recver);
printf("server/ friend accept apply send message:%s\n",mes.message);
memcpy(str,&mes,sizeof(mes));
printf("server send message:%s\n",mes.message);
printf("server send flag:%d\n",mes.flag);
if(send(recv_fd,str,sizeof(str),0)<0)
{
my_err("send error!",__LINE__);
}
}
int Get_connfd(int id)
{
server_list_t pos;
List_ForEach(list_ser,pos)
{
if(pos->data.id==id)
{
printf("用户套接字:%d\n",pos->data.connfd);
return pos->data.connfd;
}
}
return -1;
}
void Del_friend(int fd,char* buf)
{
Relation_t relation;
memcpy(&relation,buf,sizeof(relation));
printf("server/ friend send:%d\n",relation.send);
printf("server/ friend recv:%d\n",relation.recv);
printf</