admin管理员组文章数量:1609201
在Linux环境下,利用Socket通信实现网络聊天程序,主要包括以下功能:
(1)系统各菜单功能界面、聊天界面的显示
(2)用户的注册、登录(手机号注册,合格性检测,重复性检测),注册后创建用户文件夹
(3)可支持好友管理(好友列表在线显示、增删查,网络传输文件),账户管理(修改信息,权限变更(创新可调用MD5库文件)
(3)聊天方式分群聊和私聊两种方式,群聊可管理员设置禁言,代码实现禁言单用户,全员禁言代码类同(创新可加入自然语言检测,实现敏感词监督)
(4)保存聊天记录,代码实现保存私聊记录,群聊记录保存类同
(5)实现客户端之间网络传输文件
服务器每接上一个客户端,启动一个线程;
客户端创建收发线程与服务器交互。
Server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <memory.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <time.h>
#include <malloc.h>
#include <sys/stat.h>
#include <termios.h>
#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;i<counter_num;i++)
{
fread(&t,sizeof(cliMesg),1,fp);
p=p1;
while(p->next)
{
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;j<tmp->hys;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;i<n;i++)
{
fread(&t,sizeof(friMesg),1,fp);
p1=x;
while(p1->next)
{
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;i<num;i++)
{
p1=head->next;
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;i<num;i++)
{
//如果找到
if(strcmp(p->hy[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;
}
//好友列表含有信
版权声明:本文标题:Ubuntu环境下基于Socket通信的网络聊天系统 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1728560691a1163830.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论