在Linux环境下,利用Socket通信实现网络聊天程序,主要包括以下功能:
(1)系统各菜单功能界面、聊天界面的显示
(2)用户的注册、登录(手机号注册,合格性检测,重复性检测),注册后创建用户文件夹
(3)可支持好友管理(好友列表在线显示、增删查,网络传输文件),账户管理(修改信息,权限变更(创新可调用MD5库文件)
(3)聊天方式分群聊和私聊两种方式,群聊可管理员设置禁言,代码实现禁言单用户,全员禁言代码类同(创新可加入自然语言检测,实现敏感词监督)
(4)保存聊天记录,代码实现保存私聊记录,群聊记录保存类同
(5)实现客户端之间网络传输文件
服务器每接上一个客户端,启动一个线程;
客户端创建收发线程与服务器交互。
Server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NUM 1024
#define SIZE sizeof(cliMesg) //结构体cliMesg的大小
typedef long long ll;
//账户类
typedef struct client_message
{
char id[20]; //每个账号唯一id, 手机号
char passwd[20]; //账号密码
char name[50]; //账号昵称
char hy[100][20]; //好友列表,最大100个
int hys; //好友数量
int online; //0不在线, 1在线
int fd; //存放客户端成功连接后accept产生的新的套接字, 不在线为-5
int chatroom; //存放是否打开了双人聊天室,打开为1 , 没打开为0
int admin; //管理员权限 -1禁言 - 踢出不能再进
//bMesg status; //禁言
long ed_time;
struct client_message *next; //下一条链表的首地址
}cliMesg;
//信息类
typedef struct friend_message
{
char rid[20]; //收信息的人
char sid[20]; //发信息的人
int type; //信息类型 , 好友请求1 , 私聊信息 2 , 好友请求回复信息3 , 文件传输4 , 文件回复5
char mesg[1024]; //信息
char fname[1024]; //文件名
struct friend_message * next;//下一条信息的首地址
}friMesg;
cliMesg *head=NULL;
friMesg *head1=NULL;
int count =0; //账号数量
int urev_count=0; //未发送的信息
//创建账号信息的头指针
cliMesg *create_count()
{
cliMesg *p1;
p1=(cliMesg *)malloc(SIZE);
if(p1==NULL)
{
printf("create error\n");
return NULL;
}
p1->next=NULL;
//记录账户
FILE *fp;
fp=fopen("counterMsg","a+"); //打开文件
if(fp==NULL)
{
printf("open error\n");
return NULL;
}
//文件为空
if(fgetc(fp)==EOF)
{
fclose(fp);
return p1;
}
//文件有内容
rewind(fp); //文件指针重返文件头
//获取账号数量
int counter_num;
fread(&counter_num,sizeof(int),1,fp);
printf("counter_num=%d\n",counter_num);
count=counter_num;
//建立好友链表
cliMesg t;
cliMesg *tmp,*p;
int i;
for(i=0;inext)
{
p=p->next;
}
tmp=(cliMesg *)malloc(sizeof(cliMesg));
tmp->next=NULL;
strcpy(tmp->id,t.id);
strcpy(tmp->name,t.name);
strcpy(tmp->passwd,t.passwd);
tmp->admin=t.admin;
tmp->hys=t.hys;
tmp->ed_time=t.ed_time;
//有好友将数据存入好友链表
int j;
for(j=0;jhys;j++)
{
strcpy(tmp->hy[j],t.hy[j]);
}
tmp->fd= -5; //初始未登录
tmp->chatroom=0; //初始未私聊
tmp->online=0; //初始未在线
//tmp->admin=0; //初始为普通用户
p->next=tmp;
}
fclose(fp);
return p1;
}
//创建未查看信息的头指针
friMesg *create_buffmsg()
{
friMesg *x;
x=(friMesg *)malloc(sizeof(friMesg));
if(x==NULL)
{
printf("create error\n");
return NULL;
}
x->next=NULL;
FILE *fp;
fp=fopen("buffMsg","a+");
if(fp==NULL)
{
printf("open error\n");
return NULL;
}
//如果为空文件关闭文件直接返回头指针
if(fgetc(fp)==EOF)
{
fclose(fp);
return x;
}
rewind(fp);
int n;
fread(&n,sizeof(int),1,fp);
printf("urev_num=%d\n",n);
urev_count=n;
friMesg t;
friMesg *p,*p1;
//创建未查看信息链表
int i;
for(i=0;inext)
{
p1=p1->next;
}
p=(friMesg *)malloc(sizeof(friMesg));
p->next=NULL;
strcpy(p->rid,t.rid);
strcpy(p->sid,t.sid);
p->type=t.type;
strcpy(p->mesg,t.mesg);
p1->next=p;
}
fclose(fp);
return x;
}
//获取系统时间
char **get_time()
{
char **str=(char **)malloc(NUM*sizeof(char *));
time_t t;
struct tm * lt;
time (&t);//获取Unix时间戳。
lt = localtime (&t);//转为时间结构。
sprintf ( str,"%04d/%02d/%02d %02d:%02d:%02d\n",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);//输出结果
return str;
}
//保存账户信息
void saveclient()
{
FILE *fp;
fp=fopen("counterMsg","w"); //打开文件
if(fp==NULL)
{
printf("open error\n");
return;
}
printf("账户个数=%d",count);
fwrite(&count,sizeof(int),1,fp); //先保存账号个数
cliMesg* p;
p=head;
if(p->next==NULL) //如果账号列表为空 , 关闭文件并退出函数
{
fclose(fp);
return ;
}
p=p->next;
//按结构体大小保存账号信息
while(p)
{
fwrite(p,sizeof(cliMesg),1,fp);
p=p->next;
}
printf("账号信息保存成功\n");
fclose(fp);
}
//保存未查看的消息
void savefile()
{
FILE *fp;
fp=fopen("buffMsg","w");
if(fp==NULL)
{
printf("open error\n");
return;
}
printf("未查看信息个数=%d\n",urev_count);
fwrite(&urev_count,sizeof(int),1,fp);
friMesg *p;
p=head1;
if(p->next==NULL)
{
fclose(fp);
return;
}
p=p->next;
while(p)
{
fwrite(p,sizeof(cliMesg),1,fp);
p=p->next;
}
printf("信息保存成功");
fclose(fp);
}
//服务器上当前客户端id.txt保存聊天记录
void savefile2(char str[1024],char id[20])
{
FILE *fp;
char ch[1024];
sprintf(ch,"./%s/%s.txt",id,id);
fp=fopen(ch,"a+");
if(fp==NULL) //打开错误关闭程序
return ;
memset(ch,0,1024);
strcat(str,"\n"); //txt文档每行句末尾加特殊换行符
strcpy(ch,str);
fwrite(ch,strlen(ch),1,fp);
printf("聊天记录保存成功\n");
fclose(fp);
}
//帐号合格性检查
int isnum1(char s[20])
{
int i=0;
while(s[i])
{
if(!isdigit(s[i]))
{
return 0;
}
i++;
}
if(i<11)
{
return 0;
}
return 1;
}
//用户注册
void add(int fd)
{
cliMesg *p1,*p,*p2;
int leap=0; //标识符,账号是否能正确注册
p=(cliMesg *)malloc(SIZE);
if(p==NULL)
return;
char str[256];
char str1[256];
memset(str,0,sizeof(str));
memset(str1,0,sizeof(str1));
strcpy(str,"请输入您要注册的手机号");
send(fd,str,strlen(str),0);
memset(str,0,sizeof(str));
recv(fd,str,sizeof(str),0);
strcpy(str1,str);
if(!isnum1(str)) //判断是否纯数字账号
{
memset(str,0,sizeof(str));
strcpy(str,"请输入正确的手机号\n");
send(fd,str,strlen(str),0);
return;
}
p1=head;
//判断注册账户是否存在
while(p1->next)
{
if(strcmp(p1->next->id,str)==0)
{
leap=1;
break;
}
p1=p1->next;
}
if(leap==1)
{
memset(str,0,sizeof(str));
strcpy(str,"账号重复\n");
send(fd,str,strlen(str),0);
return;
}
//正常注册
strcpy(p->id,str1);
memset(str,0,sizeof(str));
strcpy(str,"请输入密码");
send(fd,str,strlen(str),0);
memset(str,0,sizeof(str));
recv(fd,str,sizeof(str),0);
strcpy(p->passwd,str);
memset(str,0,sizeof(str));
strcpy(str,"请输入昵称");
send(fd,str,strlen(str),0);
memset(str,0,sizeof(str));
recv(fd,str,sizeof(str),0);
strcpy(p->name,str);
p1=head;
while(p1->next)
{
p1=p1->next;
}
p1->next=p;
p->hys=0;
p->online=0;
p->fd=-5;
p->next=NULL;
memset(str,0,sizeof(str));
strcpy(str,"注册成功,您可以登录了\n");
send(fd,str,strlen(str),0);
count++; //全局变量账号数量+1
//保存账户信息
saveclient();
memset(str,0,sizeof(str));
sprintf(str,"mkdir ./%s",p->id);
system(str);
}
//账户匹配检查
int check_iscount(char id[20])
{
cliMesg *p;
if(head->next==NULL)
{
return 0;
}
p=head->next;
while(p)
{
if(strcmp(id,p->id)==0)
{
return 1;
}
p=p->next;
}
return 0;
}
//密码匹配检查
int check_countpasswd(char id[20],char passwd[20])
{
cliMesg *p;
if(head->next==NULL)
{
return 0;
}
p=head->next;
while(p)
{
if(strcmp(id,p->id)==0 && strcmp(passwd,p->passwd)==0)
{
return 1;
}
p=p->next;
}
return 0;
}
//判断是否在线
int countOnline(char id[20])
{
cliMesg *p;
p=head;
while(p)
{
if((strcmp(p->id,id)==0) && p->online==1)
{
return 1;
}
p=p->next;
}
return 0;
}
//好友列表
void list_friends(int fd,char id[20])
{
char sendbuf[1024]={0};
cliMesg *p,*p1;
int cnt=0;
p=head;
p=p->next;
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
int num=p->hys;
if(num==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"好友列表为空");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"***************好友列表***************");
send(fd,sendbuf,strlen(sendbuf),0);
int i;
for(i=0;inext;
char str[20]={0};
while(p1)
{
if(strcmp(p1->id,p->hy[i])==0)
{
strcpy(str,p1->name);
break;
}
p1=p1->next;
}
memset(sendbuf,0,sizeof(sendbuf));
if(p1->online==1)
cnt++;
sprintf(sendbuf,"%d 好友账号[%s],昵称[%s],[%d]\n",i+1,p->hy[i],str,p1->online);
send(fd,sendbuf,strlen(sendbuf),0);
}
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"在线好友个数=%d\n",cnt);
send(fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"**************************************");
send(fd,sendbuf,strlen(sendbuf),0);
}
//查找已加好友
void find_friends(int fd,char id[20])
{
cliMesg *p,*p1;
p=head;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
char find_id[1024]={0};
strcpy(sendbuf,"请输入您要查找的手机号");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,find_id,sizeof(find_id),0);
//查找手机号是否存在
if(check_iscount(find_id)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"此号码不存在");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
//查找自己是否有该好友
p=p->next;
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
if(p->hys==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"没有此好友");
send(fd,sendbuf,strlen(sendbuf),0);
}
int i;
int num=p->hys;
for(i=0;ihy[i],find_id)==0)
{
//将其昵称取出
p1=head->next;
char str[20]={0};
while(p1)
{
if(strcmp(p1->id,find_id)==0)
{
strcpy(str,p1->name);
break;
}
p1=p1->next;
}
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"该好友账户为%s,昵称为%s",find_id,str);
send(fd,sendbuf,strlen(sendbuf),0);
}
}
}
//删除好友
void del_friends(int fd,char id[20])
{
cliMesg *p,*p1;
int i,leap=0;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
p=head->next;
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
if(p->hys==0)
{
strcpy(sendbuf,"您的好友列表为空");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
//好友列表含有信息
memset(sendbuf,0,sizeof(1024));
strcpy(sendbuf,"输入你想删除的好友账户");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
for(i=0;i<(p->hys);i++)
{
if(strcmp(p->hy[i],recvbuf)==0)
{
//删除中间节点
while(i<(p->hys-1))
{
strcpy(p->hy[i],p->hy[i+1]);
i++;
}
memset(p->hy[i],0,sizeof(p->hy[i]));
p->hys--;
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"删除成功");
send(fd,sendbuf,strlen(sendbuf),0);
leap=1;
saveclient();
break;
}
}
//本地删除了,对方列表也要删除
if(leap==1)
{
p1=head->next;
while(p1)
{
if(strcmp(p1->id,recvbuf)==0)
{
break;
}
p1=p1->next;
}
for(i=0;i<(p1->hys);i++)
{
if(strcmp(p1->hy[i],p->id)==0)
{
while(i<(p1->hys-1))
{
strcpy(p1->hy[i],p1->hy[i+1]);
i++;
}
memset(p1->hy[i],0,sizeof(p1->hy[i]));
p1->hys--;
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"对方那也删除");
send(fd,sendbuf,strlen(sendbuf),0);
saveclient();
break;
}
}
}
else
{
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"删除失败,您没有此好友");
send(fd,sendbuf,strlen(sendbuf),0);
}
}
//添加好友
void add_friends(int fd,char id[20])
{
cliMesg *p,*p1;
int i;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
//找到自己的账户节点
p=head->next;
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
strcpy(sendbuf,"输入添加的好友手机号");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"消息已发送");
send(fd,sendbuf,strlen(sendbuf),0);
if(check_iscount(recvbuf)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"没有此账号");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
if(strcmp(recvbuf,p->id)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"不能添加自己为好友");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
//查看自己好友列表里是否有该好友
for(i=0;ihys;i++)
{
if(strcmp(recvbuf,p->hy[i])==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"此好友已添加");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
}
//如果没有该好友,得向对方发送请求
p1=head->next;
time_t timep;
while(p1)
{
if(strcmp(p1->id,recvbuf)==0)
{
friMesg *m,*m1;
m=(friMesg *)malloc(sizeof(friMesg));
m->type=1;
strcpy(m->rid,recvbuf); //收消息的人
strcpy(m->sid,p->id); //发消息的人
memset(sendbuf,0,sizeof(sendbuf));
time(&timep);
sprintf(sendbuf,"%s\n%s想添加您为好友,y同意,n不同意",ctime(&timep),p->id);
strcpy(m->mesg,sendbuf);
m->next=NULL;
m1=head1;
while(m1->next)
{
m1=m1->next;
}
m1->next=m;
urev_count++;
//如果对方在线
if(countOnline(p1->id)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p1->fd,sendbuf,strlen(sendbuf),0);
}
savefile(); //保存未发送的信息
}
p1=p1->next;
}
}
char filename[1024]={0};
char fname[1024]={0};
//文件传输
void send_file(int fd,char id[20])
{
cliMesg *p,*p1;
int i;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
memset(filename,0,sizeof(filename));
memset(fname,0,sizeof(fname));
//找到自己的账户节点
p=head->next;
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
strcpy(sendbuf,"输入好友账户");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
if(isnum1(recvbuf)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"输入格式不正确,应为11位数字!!!");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
if(check_iscount(recvbuf)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"没有此账号");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
strcpy(sendbuf,"传输文件名(完整路径) " );
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,filename,sizeof(recvbuf),0);
// printf("filename=%s\n",filename);
memset(sendbuf,0,sizeof(sendbuf));
//printf("111\n");
//printf("fname=%s\n",fname);
int f=0;
//查看自己好友列表里是否有该好友
for(i=0;ihys;i++)
{
if(strcmp(recvbuf,p->hy[i])==0)//找到
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"存在此好友\n");
send(fd,sendbuf,strlen(sendbuf),0);
f=1; break;
}
}
if(i==p->hys&&f==0)
{
if(strcmp(recvbuf,p->id)==0) //自己
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"不能给自己发送文件");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"不存在此好友");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
strcpy(sendbuf,"消息已发送");
send(fd,sendbuf,strlen(sendbuf),0);
//printf("dhgahga\n");
//向对方发送请求
p1=head->next;
time_t timep;
while(p1)
{
if(strcmp(p1->id,recvbuf)==0)
{
friMesg *m,*m1;
m=(friMesg *)malloc(sizeof(friMesg));
m->type=4;
strcpy(m->rid,recvbuf); //收文件的人
strcpy(m->sid,p->id); //发文件的人
strcpy(m->fname,filename);
char tmp[1024]={0};
int pos;
for(pos=strlen(filename)-1;filename[pos]!='/';pos--);
strncpy(tmp,filename+pos+1,strlen(filename)-pos);
memset(sendbuf,0,sizeof(sendbuf));
time(&timep);
sprintf(sendbuf,"%s\n%s正给您发文件%s,y接收,n拒绝",ctime(&timep),p->id,tmp);
strcpy(m->mesg,sendbuf);
m->next=NULL;
m1=head1;
while(m1->next)
{
m1=m1->next;
}
m1->next=m;
urev_count++;
//如果对方在线
if(countOnline(p1->id)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p1->fd,sendbuf,strlen(sendbuf),0);
}
savefile(); //保存未查看的信息
}
p1=p1->next;
}
}
//文件保存
void save_file(char id[1024],char f[1024])
{
//printf("save_file : %s\n",f);
FILE *p1,*p2;
p1=fopen(f,"r");
if(p1==NULL)
{
printf("%s can not read!\n",f);
return ;
}
int pos;
//printf("222\n");
for(pos=strlen(f)-1;f[pos]!='/';pos--);
strncpy(fname,f+pos+1,strlen(f)-pos);
//printf("read ok\n");
char s_path[1024]={0};
sprintf(s_path,"./%s/%s",id,fname);
printf("%s\n",s_path);
p2=fopen(s_path,"wb+");
if(p2==NULL)
{
printf("%s can not open!\n",s_path);
return ;
}
char buf[1024];
int r_len;
while((r_len=fread(buf,sizeof(char),1024,p1))>0)
{
printf("write ok\n");
fwrite(buf,sizeof(char),r_len,p2);
}
fclose(p1);
fclose(p2);
}
char a[100][20]; //存放聊天室人的id
int len=0; //聊天室人数
//多人聊天
void multi_chat(int fd,char id[20])
{
char sendbuf[1024]={0};
char recvbuf[1024]={0};
strcpy(sendbuf,"您已进入聊天室,输入quit退出,输入look查看当前人");
send(fd,sendbuf,sizeof(sendbuf),0);
strcpy(a[len],id);
len++;
int i;
cliMesg *p;
time_t timep,bt;
time(&timep);
printf("id为%s 用户进入群聊 %s",id,get_time());
int bflag=0; //禁言消息
while(1)
{
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
//退出群聊室
if(strcmp(recvbuf,"quit")==0)
{
for(i=0;inext;
while(p)
{
if(strcmp(p->id,a[i])==0)
{
//向还在群里的人发送通知
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s退出聊天室",id);
send(p->fd,sendbuf,strlen(sendbuf),0);
break;
}
p=p->next;
}
}
return ;
}
//查看当前群里有多少人
if(strcmp(recvbuf,"look")==0)
{
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"当前聊天室有%d人,他们是:\n",len);
send(fd,sendbuf,strlen(sendbuf),0);
for(i=0;inext;
while(p)
{
if(strcmp(p->id,a[i])==0)
{
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"昵称是%s 账户是%s admin=%d",p->name,p->id,p->admin);
send(fd,sendbuf,strlen(sendbuf),0);
break;
}
p=p->next;
}
}
continue;
}
//printf("!!p12123123123\n");
cliMesg *p1;
p1=head->next;
while(p1) //匹配发消息用户
{
if(strcmp(p1->id,id)==0)
{
break;
}
p1=p1->next;
}
//printf("!!p11111->admin\n");
//设置全员禁言
if(strcmp(recvbuf,"total silence"))
{
}
//设置单用户禁言
if(strcmp(recvbuf,"silence+")==0)
{
if(p1->admin==1)//是管理员
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"输入禁言用户帐号");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(sendbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
//printf("recvbuf=%s\n",recvbuf);
int f=0;
for(i=0;inext;
while(p)
{
if(strcmp(p->id,a[i])==0 &&strcmp(p->id,recvbuf)==0)
{
f=1;break;
}
p=p->next;
}
if(f) break;
}
//printf("p->admin=%d\n",p->admin);
//printf("p->id=%s\n",p->id);
if(p->admin==1) //同级不能禁言对方
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"同等级不能禁言");
send(fd,sendbuf,strlen(sendbuf),0);
continue;
}
else //被禁言
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"禁言时长[单位/分]");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,strlen(sendbuf),0);
// printf("sendbuf==%s\n",sendbuf);
// printf("recvbuf==%s\n",recvbuf);
int tmp;
sscanf(recvbuf,"%d",&tmp);
printf("tmp==%d\n",tmp);
//tmp*=60; //时间转换
bt=time(NULL);
//printf("bt=%ld\n",bt);
//printf("p->admin=%d\n",p->admin);
p->admin=-1;
//p->status.st=bt;
printf("st=%ld\n",bt);
//p->status.ed=(bt+tmp*60);
printf("ed=%ld\n",bt+tmp*60);
p->ed_time=bt+tmp*60;
printf("已禁言用户%s\n",p->id);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"禁言成功");
send(fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您已被禁言,无法与群友交流!");
send(p->fd,sendbuf,strlen(sendbuf),0);
saveclient();
//continue;
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"\t%s\t[%s用户被你禁言%d分钟]",get_time(),p->name,tmp);
strcpy(recvbuf,sendbuf);
send(p1->fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"\t%s\t[%s用户被%s禁言%d分钟]",get_time(),p->name,p1->name,tmp);
strcpy(recvbuf,sendbuf);
//send(p->fd,sendbuf,strlen(sendbuf),0);
bflag=1;
}
}
else //不是管理员
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"普通用户无禁言权限");
send(fd,sendbuf,strlen(sendbuf),0);
continue;
}
}
//printf("!!p->admin=%d\n",p->admin);
if(p1->admin==-1) //发消息用户处于禁言状态
{
printf("now bt=%ld\n",time(NULL));
if((bt=time(NULL))ed_time)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"处于禁言状态");
send(p1->fd,sendbuf,strlen(sendbuf),0);
continue ;
}
else
{
p1->admin=0;
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"解禁");
send(p1->fd,sendbuf,strlen(sendbuf),0);
saveclient();
}
}
//printf("bflag=%d\n",bflag);
//printf("recvbuf=%s\n",recvbuf);
if(bflag) //群发禁言消息
{
for(i=0;inext;
while(p)
{
if(strcmp(p->id,a[i])==0&&strcmp(p->id,id)!=0)
{
//printf("id====%s\n",p->id);
//memset(sendbuf,0,sizeof(sendbuf));
send(p->fd,recvbuf,strlen(recvbuf),0);
break;
}
p=p->next;
}
}
bflag=0;
continue;
}
//群发普通消息
for(i=0;inext;
while(p)
{
if(strcmp(p->id,a[i])==0&&strcmp(p->id,id)!=0)
{
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s %s %s",p1->name,get_time(),recvbuf);
send(p->fd,sendbuf,strlen(sendbuf),0);
break;
}
p=p->next;
}
}
}
}
//修改个人信息
void modify(int fd,char id[20])
{
cliMesg *p,*p1;
int i;
char sendbuf[1024]={0};
char recvbuf[1024]={0};
p=head->next;
while(1)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
sprintf(sendbuf,"我的昵称:%s\n我的账户:%s\n我的密码:%s\n我的身份:%s\n",p->name,p->id,p->passwd,p->admin==1?"管理员":"普通用户");
send(fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"\t\t*********功能选项************\n\t\t\t1.修改昵称\n\n\t\t\t2.修改密码\n\n\t\t\t3.权限变更\n\n\t\t\t0.退出\n\t\t*****************************");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
if(strcmp(recvbuf,"1")==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"请输入新的昵称");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
strcpy(p->name,recvbuf);
saveclient();
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"昵称修改成功");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
else if(strcmp(recvbuf,"2")==0) //输入2修改密码
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"请输入新的密码");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
strcpy(p->passwd,recvbuf);
saveclient();
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"密码修改成功");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
else if(strcmp(recvbuf,"3")==0)
{
if(p->admin==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"已是最高权限,无需变更");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"请输入授权码");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
if(strcmp(recvbuf,"linux")!=0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"授权码有误!!");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
p->admin=1;
saveclient();
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"授权成功, 已变更为管理员");
send(fd,sendbuf,strlen(sendbuf),0);
return ;
}
else if(strcmp(recvbuf,"0")==0)
{
return;
}
else
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"输入非法");
send(fd,sendbuf,strlen(sendbuf),0);
}
}
//双人聊天
void double_chat(int fd,char id[20])
{
int flags=1;
cliMesg *p;
p=head->next;
time_t timep;
time(&timep);
char recvbuf[1024]={0};
char sendbuf[1024]={0};
char str[1024]={0};
int ret=0;
strcpy(sendbuf,"输入你想聊天的好友账户");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
strcpy(str,recvbuf);
if(isnum1(str)==0){
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"输入格式不正确,应为11位数字!!!");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
//查找账户是否存在
if(check_iscount(str)==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"此号码不存在");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
if(strcmp(recvbuf,id)==0) //不能与自己聊天
{
memset(sendbuf,0,1024);
strcpy(sendbuf,"不能与自己聊天");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
cliMesg *p1;
p1=head->next;
while(p1)
{
if(strcmp(p1->id,str)==0)
{
break;
}
p1=p1->next;
}
/*
memset(sendbuf,0,1024);
sprintf(sendbuf,"flags=%d",p1->chatroom);
send(fd,sendbuf,strlen(sendbuf),0);
*/
if(p1->chatroom==0)
{
while(p)
{
if(strcmp(p->id,id)==0)
{
break;
}
p=p->next;
}
if(p->hys==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"没有此好友");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
/*cliMesg *p1;
p1=head->next;
while(p1)
{
if(strcmp(p1->id,recvbuf)==0)
{
break;
}
p1=p1->next;
}*/
if(p1->fd==-5) //判断好友在不在线和有没有打开聊天窗口
{
memset(sendbuf,0,1024);
strcpy(sendbuf,"好友不在线");
send(fd,sendbuf,1024,0);
return;
}
int i;
int num=p->hys;
for(i=0;ihy[i],str)==0)
{
flags=0;
memset(sendbuf,0,1024);
//p->chatroom=1;
p1->chatroom=1;
strcpy(sendbuf,"连接成功");
send(fd,sendbuf,strlen(sendbuf),0);
}
}
if(flags==1)
{
memset(sendbuf,0,1024);
strcpy(sendbuf,"请先添加该好友");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
//进入聊天室
while(1) //进入聊天,输入quit退出
{
memset(recvbuf,0,1024);
memset(sendbuf,0,1024);
recv(fd,recvbuf,1024,0);
if(strcmp(recvbuf,"quit")==0)
{
p->chatroom=0;
memset(sendbuf,0,1024);
if(p1->chatroom!=0)
sprintf(sendbuf,"%s 已退出,请您输入quit退出",id);
send(p1->fd,sendbuf,1024,0);
break;
}
memset(sendbuf,0,1024);
sprintf(sendbuf,"%s %s %s",p->name,get_time(),recvbuf);
savefile2(sendbuf,id);//保存聊天记录
savefile2(sendbuf,p1->id);
send(p1->fd,sendbuf,1024,0);
memset(recvbuf,0,1024);
memset(sendbuf,0,1024);
// recv(p1->fd,recvbuf,1024,0);
// sprintf(sendbuf,"%s$$$$$%s say:%s",ctime(&timep),p1->id,recvbuf);
// savefile2(sendbuf,id);//保存聊天记录
//savefile2(sendbuf,p1->id);
//send(fd,sendbuf,1024,0);
}
}else
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"该好友正在聊天");
send(fd,sendbuf,strlen(sendbuf),0);
}
}
//好友管理
void manage_friends(int fd,char id[20])
{
char sendbuf[1024]={0};
char recvbuf[1024]={0};
strcpy(sendbuf,"\n\t\t*********功能选项***********\n\n\t\t1.好友列表\t2.查找好友\n\n\t\t3.删除好友\t4.添加好友\n\n\t\t5.文件传输\t0.退出\n\t\t****************************\n");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
if(strcmp(recvbuf,"1")==0)
{
//好友列表
list_friends(fd,id);
}
if(strcmp(recvbuf,"2")==0)
{
find_friends(fd,id);
}
/*
if(strcmp(recvbuf,"2")==0)
{
display_friends(fd,id);
}
*/
if(strcmp(recvbuf,"3")==0)
{
del_friends(fd,id);
}
if(strcmp(recvbuf,"4")==0)
{
//添加朋友消息
add_friends(fd,id);
}
if(strcmp(recvbuf,"5")==0)
{
//文件传输
send_file(fd,id);
}
if(strcmp(recvbuf,"0")==0)
{
return;
}
}
//在线从服务器查看聊天记录
void jilu(int fd,char id[20])
{
int fp; //文件标识符
char str[1024];
sprintf(str,"./%s/%s.txt",id,id); //打开相应人的聊天记录文本文件
fp=open(str,O_RDONLY); //只读方式打开
if(fp==-1)
{
memset(str,0,1024);
strcpy(str,"您没有聊天记录");
send(fd,str,strlen(str),0);
return;
}
int ret;
memset(str,0,1024);
while(ret=read(fp,str,1024)) //ret读的长度,为0退出while
{
write(fd,str,strlen(str)); //读出来发送给客户端
memset(str,0,1024);
}
close(fp);
}
//下载聊天记录
void load(int fd,char id[20])
{
int fp;
char sendbuf[1024];
char recvbuf[1024]={0};
char str[1024]={0};
sprintf(sendbuf,"./%s/%s.txt",id,id);
fp=open(sendbuf,O_RDONLY);
if(fp==-1) //先判断有没有聊天记录文件
{
memset(sendbuf,0,1024);
strcpy(sendbuf,"您没有聊天记录");
send(fd,sendbuf,strlen(sendbuf),0);
return;
}
int ret;
memset(sendbuf,0,1024);
strcpy(sendbuf,"xiazai");
send(fd,sendbuf,strlen(sendbuf),0);
recv(fd,recvbuf,sizeof(recvbuf),0);
memset(sendbuf,0,1024);
sprintf(sendbuf,"%s",id);
send(fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,1024);
while(ret=read(fp,sendbuf,1024))
{
send(fd,&ret,sizeof(int),0); //先发送内容字节数,再发送内容
send(fd,sendbuf,ret,0);
memset(sendbuf,0,1024);
}
memset(sendbuf,0,1024);
strcpy(sendbuf,"endend");
ret = strlen(sendbuf); //结束后发送消息告诉客户端发送完毕
send(fd,&ret,sizeof(int),0);
send(fd,sendbuf,strlen(sendbuf),0);
//memset(sendbuf,0,1024);
// sprintf(str," 存储在./%s.txt中",id);
//strcpy(sendbuf,str);
//send(fd,sendbuf,strlen(sendbuf),0);
close(fp);
}
//处理客户端的信息
void *handlerClient(void *arg)
{
int fd=*(int *)arg;
char recvbuf[1024]={0};
char recvbuf1[1024]={0};
char sendbuf[1024]={0};
int ret;
//接受数据
if((ret=recv(fd,recvbuf,sizeof(recvbuf),0))==-1)
{
perror("recv");
return NULL;
}
printf("client say:%s\n",recvbuf);
while(1)
{
//system("clear");
memset(sendbuf,0,sizeof(sendbuf));
//登录界面
strcpy(sendbuf,"\n\t\t*****欢迎使用网络聊天系统*****\n\t\t\t菜单选项\n\n\t\t\t1.登录\n\n\t\t\t2.注册\n\n\t\t\t0.退出\n\t\t******************************\n");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
memset(recvbuf1,0,sizeof(recvbuf1));
//接受客户端的数据
if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
{
perror("recv");
return NULL;
}
if(strcmp(recvbuf,"1")==0) //登录
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"请输入账号");
if(send(fd,sendbuf,strlen(sendbuf),0)==-1)
{
perror("send");
return NULL;
}
if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
{
perror("recv");
return NULL;
}
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"请输入密码");
if(send(fd,sendbuf,strlen(sendbuf),0)==-1)
{
perror("send");
return NULL;
}
//struct termios settings;
//char tmppwd[50];
//tcgetattr(fileno(stdin),&settings);
//settings.c_lflag&=~ECHO;
// tcsetattr(fileno(stdin),TCSANOW,&settings);
// fgets(tmppwd,50,stdin);
// strcpy(recvbuf1,tmppwd);
if(recv(fd,recvbuf1,sizeof(recvbuf1),0)==-1)
{
perror("recv");
return NULL;
}
//else{
// printf("@recvbuf1=%s",recvbuf1);
// }
//匹配账号密码是否存在且正确
//printf("!!recvbuf=%s\n",recvbuf);
if(check_iscount(recvbuf)==0 ||check_countpasswd(recvbuf,recvbuf1)==0)
{
//printf("recvbuf1=%s",recvbuf1);
//printf("recvbuf=%s\n",recvbuf);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"输入账号或密码不正确");
send(fd,sendbuf,strlen(sendbuf),0);
continue;
}
//判断该账号是否在线
else if(countOnline(recvbuf)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"此账号已在线");
send(fd,sendbuf,strlen(sendbuf),0);
continue;
}
else
{
strcpy(recvbuf1,recvbuf);
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"登录成功 ");
cliMesg *p;
p=head;
char str[50];
while(p->next)
{
if((strcmp((p->next)->id,recvbuf1)==0))
{
(p->next)->online=1;
(p->next)->fd=fd;
(p->next)->chatroom=0;
strcpy(str,(p->next)->name);
}
p=p->next;
}
send(fd,sendbuf,strlen(sendbuf),0);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"\n\n%s , 你好! ",str);
send(fd,sendbuf,strlen(sendbuf),0);
//登录时判断是否有新消息
friMesg *p9;
p9=head1;
int len=0;
while(p9)
{
if(strcmp(p9->rid,recvbuf1)==0)
{
len=1;
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看\n");
send(fd,sendbuf,strlen(sendbuf),0);
break;
}
p9=p9->next;
}
//主界面
memset(recvbuf,0,sizeof(recvbuf));
while(1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"\n\n\t\t*********菜单选项************\n\t\t1.好友管理\t2.账户管理\n\n\t\t3.群聊世界\t4.私聊世界\n\n\t\t5.查看记录\t6.下载记录\n\n\t\t\t 0.退出\n\t\t*****************************\n");
send(fd,sendbuf,strlen(sendbuf),0);
memset(recvbuf,0,sizeof(recvbuf));
if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
{
perror("recv");
return NULL;
}
//printf("buf=%s",recvbuf);
//对主界面进行分析
if(strcmp(recvbuf,"1")==0)
{
//好友管理
manage_friends(fd,recvbuf1);
}
if(strcmp(recvbuf,"2")==0)
{
//账户管理
modify(fd,recvbuf1);
}
if(strcmp(recvbuf,"3")==0)
{
//群聊
multi_chat(fd,recvbuf1);
}
if(strcmp(recvbuf,"4")==0)
{
//私聊
double_chat(fd,recvbuf1);
}
if(strcmp(recvbuf,"5")==0)
{
jilu(fd,recvbuf1);
}
if(strcmp(recvbuf,"6")==0)
{
load(fd,recvbuf1);
}
//打开信息
if(strcmp(recvbuf,"open")==0)
{
friMesg *m;
int flags=0;
m=head1->next;
printf("urev_count=%d\n",urev_count);
while(m)
{
if(strcmp(m->rid,recvbuf1)==0)
{
flags=1;
if(m->type==1) //1为好友请求消息
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,m->mesg);
send(fd,sendbuf,strlen(sendbuf),0);
//有两种情况 同意或不同意
while(1)
{
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
if(strcmp(recvbuf,"y")==0)
{
m->type=3; //好友请求回复
strcpy(m->rid,m->sid);
strcpy(m->sid,recvbuf1);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s已同意添加,添加成功",recvbuf1);
strcpy(m->mesg,sendbuf);
cliMesg *p1;
p=head->next;
p1=head->next;
//收消息的人
while(p)
{
if(strcmp(p->id,m->rid)==0)
{
break;
}
p=p->next;
}
//发消息的人
while(p1)
{
if(strcmp(p1->id,m->sid)==0)
{
break;
}
p1=p1->next;
}
//同意往好友列表添信息
strcpy(p->hy[p->hys],p1->id);
p->hys++;
strcpy(p1->hy[p1->hys],p->id);
p1->hys++;
if(countOnline(m->rid)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p->fd,sendbuf,strlen(sendbuf),0);
}
saveclient();
savefile();
break;
}else if(strcmp(recvbuf,"n")==0)
{
cliMesg *p;
p=head->next;
while(p)
{
if(strcmp(p->id,m->sid)==0)
{
break;
}
p=p->next;
}
m->type=3; //发消息
strcpy(m->rid,m->sid);
strcpy(m->sid,recvbuf1);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s已拒绝添加请求,添加失败",recvbuf1);
strcpy(m->mesg,sendbuf);
if(countOnline(m->rid)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p->fd,sendbuf,strlen(sendbuf),0);
}
savefile();
break;
}
}
}
else if(m->type==2) //好友消息
{
}
else if(m->type==3)//好友请求回复
{
flags=1;
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,m->mesg);
send(fd,sendbuf,strlen(sendbuf),0);
friMesg *m1,*m2;
m1=head1;
while(m1->next)
{
if(strcmp(m1->next->rid,recvbuf1)==0)
{
m2=m1->next;
m1->next=m2->next;
free(m2);
break;
}
m1=m1->next;
}
urev_count--;
savefile();
if(m==NULL);
break;
}
else if(m->type==4)//好友文件传输请求
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,m->mesg);
send(fd,sendbuf,strlen(sendbuf),0);
//有两种情况 接收或拒绝
while(1)
{
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
if(strcmp(recvbuf,"y")==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,m->fname);
send(fd,sendbuf,strlen(sendbuf),0);
save_file(recvbuf1,m->fname);
m->type=5; //回复
strcpy(m->rid,m->sid);
strcpy(m->sid,recvbuf1);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s已同意接收文件",recvbuf1);
strcpy(m->mesg,sendbuf);
cliMesg *p1;
p=head->next;
p1=head->next;
//收文件的人
while(p)
{
if(strcmp(p->id,m->rid)==0)
{
break;
}
p=p->next;
}
//发文件的人
while(p1)
{
if(strcmp(p1->id,m->sid)==0)
{
break;
}
p1=p1->next;
}
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"文件已存储在./%s/%s\n",p1->id,fname);
//strcpy(sendbuf,"文件已存储");
send(p1->fd,sendbuf,strlen(sendbuf),0);
if(countOnline(m->rid)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p->fd,sendbuf,strlen(sendbuf),0);
}
saveclient();
savefile();
break;
}
else if(strcmp(recvbuf,"n")==0)
{
cliMesg *p;
p=head->next;
while(p)
{
if(strcmp(p->id,m->sid)==0)
{
break;
}
p=p->next;
}
m->type=5; //发消息
strcpy(m->rid,m->sid);
strcpy(m->sid,recvbuf1);
memset(sendbuf,0,sizeof(sendbuf));
sprintf(sendbuf,"%s已拒绝接收文件",recvbuf1);
strcpy(m->mesg,sendbuf);
if(countOnline(m->rid)==1)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"您有新消息,请输入open查看");
send(p->fd,sendbuf,strlen(sendbuf),0);
}
savefile();
break;
}
}
}
else if(m->type==5)//文件请求回复
{
flags=1;
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,m->mesg);
send(fd,sendbuf,strlen(sendbuf),0);
friMesg *m1,*m2;
m1=head1;
while(m1->next)
{
if(strcmp(m1->next->rid,recvbuf1)==0)
{
m2=m1->next;
m1->next=m2->next;
free(m2);
break;
}
m1=m1->next;
}
urev_count--;
savefile();
if(m==NULL);
break;
}
}
if(m==NULL)
{
break;
}
m=m->next;
}
}
//退出
if(strcmp(recvbuf,"0")==0)
{
p=head;
while(p->next)
{
if(strcmp(p->next->id,recvbuf1)==0)
{
p->next->online=0;
p->next->fd=-5;
p->next->chatroom=0;
break;
}
p=p->next;
}
break;
}
}
}
}
else if(strcmp(recvbuf,"2")==0)
{
//注册添加账户
add(fd);
}
else if(strcmp(recvbuf,"0")==0)
{
memset(sendbuf,0,sizeof(sendbuf));
strcpy(sendbuf,"欢迎下次再来");
send(fd,sendbuf,strlen(sendbuf),0);
printf("client say:bye bye\n");
break;
}
else
{
continue;
}
}
close(fd);
}
//判断客户端是否依旧在线
void * judgeClient(void)
{
cliMesg* p;
char fa[1024];
p=head;
//判断是否断开连接 , 如果断开将此账号置为不在线状态,监听套接字-5
while(1)
{
p=head->next;
while(p)
{
if(p->online==1) //在线
{
struct tcp_info info;
int len=sizeof(info);
getsockopt(p->fd,IPPROTO_TCP,TCP_INFO,&info,(socklen_t*)&len);
if((info.tcpi_state!=TCP_ESTABLISHED)) //已断开建立
{
p->online=0;
p->fd=-5;
}
}
p=p->next;
}
}
}
//主函数建立连接
int main()
{
int sockfd=0,confd=0; //定义并初始化
int chlid=0;
int ret=0;
int len=sizeof(struct sockaddr);
struct sockaddr_in myaddr;
struct sockaddr_in otheraddr;
memset(&myaddr,0,len);
memset(&otheraddr,0,len);
sockfd = socket(AF_INET, SOCK_STREAM,0);
//初始化结构体
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3333);
myaddr.sin_addr.s_addr=htonl(INADDR_ANY);//自动获取本机ip地址
int reuse = 1;
//重用socket
//如果已处在established状态下的socket调用closesocket,一般不会立即关闭而经历time_wait过成后继续重用socket
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt error\n");
return -1;
}
//绑定套接字
if(bind(sockfd,(struct sockaddr*)&myaddr,len)==-1)
{
perror("bind");
return -1;
}
//开始侦听
if((listen(sockfd,10))==-1)
{
perror("listen");
return -1;
}
printf("server waitting......\n");
//创建线程
pthread_t id1,id2;
head=create_count(); //创建账号信息的头结点
head1=create_buffmsg(); //创建缓存信息的头结点
//接收客户端请求, 创建线程
while(1)
{
//接受客户端信息
if((confd=accept(sockfd,(struct sockaddr *)&otheraddr,&len))==-1)
{
perror("accept");
return -1;
}
//输出客户端的编号 、ip和端口
printf("client fd=%d server fd=%d\n",confd,sockfd);
printf("client ip=%s port=%d\n",inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port));
//处理客户端
pthread_create(&id1,NULL,handlerClient,&confd);
//判断客户端是否在线
pthread_create(&id2,NULL,(void *)judgeClient,&confd);
pthread_detach(id1);//线程结束后资源系统自动回收
pthread_detach(id2);
}
//关闭网络连接
close(sockfd);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//接受服务器的信息
void *recvMessage(void *arg)
{
int fd=*(int *)arg;
int ret=0;
char recvbuf[1024];
char sendbuf[1024];
char str[1024];
while(1)
{
memset(recvbuf,0,sizeof(recvbuf));
memset(str,0,sizeof(str));
if((ret=recv(fd,recvbuf,sizeof(recvbuf),0))==-1)
{
return NULL;
}
//printf("hhhh:%s\n",recvbuf);
if(strcmp(recvbuf,"xiazai")==0)
{
strcpy(sendbuf,"enter xiazai");
send(fd,sendbuf,strlen(sendbuf),0);
//printf("!!!!\n");
memset(recvbuf,0,sizeof(recvbuf));
recv(fd,recvbuf,sizeof(recvbuf),0);
//printf("recvbuf:%s\n",recvbuf);
sprintf(str,"rm -f ./%s/mesg.txt",recvbuf);
//printf("str:%s\n",str);
system(str);//确保本地没有此文件
int fp; //文件标识符
sprintf(str,"./%s/mesg.txt",recvbuf);
//printf("!!!str:%s\n",str);
fp=open(str,O_WRONLY|O_CREAT|O_TRUNC,0666);
memset(recvbuf,0,1024);
//接收数据,如果“endend”表示接收结束
while(1)
{
recv(fd,&ret,sizeof(int),0);
recv(fd,recvbuf,ret,0);
if(strncmp(recvbuf,"endend",6)==0)
{
break;
}
write(fp,recvbuf,ret);
}
close(fp);
continue;
}
if(strcmp(recvbuf,"连接成功")==0)
{
system("clear");
}
puts(recvbuf);
if(ret==0)
{
exit(0);
}
}
}
//给服务器发消息
void *sendMessage(void *arg)
{
//发送
int fd=*(int *)arg;
char sendmsg[1024];
while(1)
{
memset(sendmsg,0,sizeof(sendmsg));
scanf("%s",sendmsg);
if(send(fd,sendmsg,strlen(sendmsg),0)==-1)
{
return NULL;
}
}
}
//主函数建立连接
int main(int argc,char *argv[])
{
int sockfd=0;
int ret=0;
int len=sizeof(struct sockaddr);
struct hostent *host;
struct sockaddr_in otheraddr;
memset(&otheraddr,0,len);
if(argc!=2)
{
fprintf(stderr,"Usage:%s hostname \a\n",argv[0]);
exit(1);
}
//使用hostname查询host 名字
if((host=gethostbyname(argv[1]))==NULL)
{
perror("Gethostname");
return -1;
}
//tcp套接字连接
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("sockfd");
return -1;
}
//初始化结构体,把服务器ip地址和端口号
otheraddr.sin_family = AF_INET;
otheraddr.sin_port = htons(3333);
otheraddr.sin_addr=*((struct in_addr *)host->h_addr);
//连接服务器
if(connect(sockfd,(struct sockaddr*)&otheraddr,len)==-1)
{
perror("connect");
return -1;
}
printf("connect sucess……\n");
//printf("connect success...client fd=%d\n",sockfd);
printf("client ip=%s,port=%d\n",inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port));
char recvbuf[1024]={0};
char sendbuf[1024]={0};
//给服务器 发送信息
strcpy(sendbuf,"client connect success");
if(send(sockfd,sendbuf,strlen(sendbuf),0)==-1)
{
perror("send");
return -1;
}
if(recv(sockfd,recvbuf,sizeof(recvbuf),0)==-1)
{
perror("recv");
return -1;
}
printf("server say:%s\n",recvbuf);
//创建收发线程
pthread_t id1,id2;
pthread_create(&id1,NULL,sendMessage,&sockfd);
pthread_create(&id2,NULL,recvMessage,&sockfd);
//等待发送线程结束
pthread_join(id1,NULL);
return 0;
}
编译执行
gcc server.c -o server -lpthread gcc client.c -o client -lpthread ./server ifconfig(查看主机ip地址) ./client ip地址