基于局域网的QQ模拟实现过程(简易聊天软件)

  1. 用户名注册与登录
  2. 实现客户端通用,连接同一台服务器即可聊天;
  3. 能实现上下线提醒;
  4. 客户端查看在线列表;
  5. 可以传输文件;

客户端:

/*
 * 客户端
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/select.h>
#include<sys/time.h>
#include<sys/stat.h>
#include<sys/ipc.h>
#include<signal.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<pthread.h>

#define SERVERIP	"192.168.43.229"
#define SERVERPORT	8080


struct message		//消息结构体
{
	char flag[15];	//标志位
	char name[20];	//用户名
	char msg[1024];	//消息内容
	char addressee[20];	//传输文件目的用户
	int size;		//传输内容的字节数
	char woc[10][20];
};

struct view
{
	int num;
	char name[10];
};
char locname[20];

int Register(struct message a);
void log_user(struct message *a,int cfd);
int login_success(struct message a,int cfd);
int Interface();
int help(char str[]);
void handlerecvmsg(int *cfd);
void login_notice(struct message buf,int cfd);
void leave_notice(struct message buf,int cfd);
void send_allpeople(struct message a,int cfd);
void send_personal(struct message a,int connfd);
void send_file(int cfd,char *name);
void recv_file(struct message msg,int cfd);
int main(void)
{
	struct message a;
	struct message msg;
	int cfd;
	time_t timep;
		//连接服务器
		cfd=socket(AF_INET,SOCK_STREAM,0);
		perror("socket");
		struct sockaddr_in saddr;
		bzero(&saddr,sizeof(struct sockaddr_in));	//清空地址结构
		saddr.sin_family=AF_INET;
		saddr.sin_port=htons(SERVERPORT);
		saddr.sin_addr.s_addr=inet_addr(SERVERIP); 
		//connect(cfd,(const struct sockaddr*)&saddr,sizeof(struct sockaddr));
		//perror("connect");
	while(1)
	{
		//界面
		int num;
		num=Interface();

		switch (num)
		{
				case 1://注册
					{
						Register(a);
						break;
					}

				case 2://登录
						connect(cfd,(const struct sockaddr*)&saddr,sizeof(struct sockaddr));
						perror("connect"); 
						printf("cfd:%d\n",cfd);
						log_user(&a,cfd);
						if(strcmp(a.msg,"login,success!")==0)
						{
							while(1)
							{
								login_success(a,cfd);
							}
						}
						exit(3);
						break;
					

				case 3://退出
					{
						close(cfd);
						printf("离开聊天室!\n");
						exit(1);
						break;
					}
				default:
					{
						break;
					}
		}
	}
	close(cfd);
	return 0;
}

/*
 * 函数名:Register
 * 功能:注册
 * 传入参数:struct message a
 * 返回值:0
 */
int Register(struct message a)
{
		int ccfd;
		ccfd=socket(AF_INET,SOCK_STREAM,0);
		perror("socket");
		struct sockaddr_in saddr;
		bzero(&saddr,sizeof(struct sockaddr_in));	//清空地址结构
		saddr.sin_family=AF_INET;
		saddr.sin_port=htons(SERVERPORT);
		saddr.sin_addr.s_addr=inet_addr(SERVERIP);
		connect(ccfd,(const struct sockaddr*)&saddr,sizeof(struct sockaddr));
		perror("connect");
	char password_t[20];
	printf("请输入用户名(10字以内):\n");
	memset(a.name,0,strlen(a.name));
	scanf("%s",a.name);
	while(1)
	{
		printf("请输入密码(20位以内):\n");
		memset(a.msg,0,strlen(a.msg));
		scanf("%s",a.msg);
		printf("请再次输入密码:\n");
		memset(password_t,0,strlen(password_t));
		scanf("%s",password_t);
		if(strcmp(a.msg,password_t)!=0 || strlen(a.msg)>20 || strlen(password_t)>20)
		{
			printf("密码错误!\n");
		}
		else
		{
			break;
		}
	}
	strcpy(a.flag,"reg");
	printf("%d\n",ccfd);
	send(ccfd,&a,sizeof(struct message),0);
	printf("正在注册,请稍后.....\n");
	recv(ccfd,&a,sizeof(struct message),0);
	printf("recv the message from server:%s\n",a.msg);
	close(ccfd);
	sleep(1);
}



/*
 * 函数名:	log_user
 * 功能:	用户登录
 * 传入参数:struct message *a,int cfd
 * 返回值:	无
 */
void log_user(struct message *a,int cfd)
{
	printf("请输入用户名(10字以内):\n");
	memset(a->name,0,strlen(a->name));
	scanf("%s",a->name);
	strcpy(locname,a->name);
	printf("请输入密码(20位以内):\n");
	memset(a->msg,0,strlen(a->msg));
	scanf("%s",a->msg);
	strcpy(a->flag,"login");
	send(cfd,a,sizeof(*a),0);
	printf("正在登录,请稍后....\n");
	recv(cfd,a,sizeof(*a),0);
	printf("%s\n",a->msg);
}



/*
 * 函数名:		login_success
 * 功能:		登录成功进入聊天模式
 * 传入参数:	struct message *a,int cfd
 * 返回值: 	退出返回0,否则返回1
 */
int login_success(struct message a,int cfd)
{
	char str[1024];
	char buf[1024];
	time_t timep;
	pthread_t pid;
	pthread_create(&pid,NULL,(void *)handlerecvmsg,(void *)&cfd);//创建接受消息线程
	system("clear");
	login_notice(a,cfd);	//上线通知
	printf("尊敬的%s你好,如需帮助请输入:.help\n",locname);
	while(1)
	{
		memset(a.msg,0,strlen(a.msg));
		memset(str,0,strlen(str));
		printf("TO:\n");
		scanf("%s",str);
		if(1==help(str))	//提示信息
		{
			continue;
		}
		strcpy(a.name,locname);
		strcpy(a.flag,str);
		if(strcmp(a.flag,"exit")==0)
		{
			leave_notice(a,cfd);
			send(cfd,&a,sizeof(struct message),0);
			exit(0);
		}
		else if(strcmp(a.flag,"view")==0)
		{
			send(cfd,&a,sizeof(struct message),0);		//请求查看在线用户
			continue;
		}
		else if(strcmp(a.flag,"all")==0)
		{
			send_allpeople(a,cfd);
			continue;
		}
		else if(strcmp(a.flag,"tran")==0)
		{
			printf("===选择你要发送的用户====\n");
			scanf("%s",a.name);
			send_file(cfd,a.name);
		}
		else if(strcmp(a.flag,"personal")==0)
		{
			send_personal(a,cfd);
			continue;
		}
		else
			continue;
	}

}



/*
 * 函数名:Interface
 * 功能:登录界面
 * 传入参数:无
 * 返回值:do_number
 */
int Interface()
{
	int do_number;
	do
	{
		system("clear");
		printf("\n====================");
		printf("\n===欢迎进入聊天室===");
		printf("\n======1.注册========");
		printf("\n======2.登录========");
		printf("\n======3.退出========");
		printf("\n====================\n");
		printf("选择你要执行的功能(1-3):");
		scanf("%d",&do_number);
	}while((do_number!=1)&&(do_number!=2)&&(do_number!=3));
	return do_number;
}



/*
 * 函数名:help
 * 功能:帮助
 * 传入参数:char str[]
 * 返回值:成功返回1,否则返回0
 */
int help(char str[])
{
	if(strcmp(str,".help")==0)
	{
		system("clear");
		printf("=========================================\n");
		printf("尊敬的%s用户,你好:\n",locname);
		printf("all$------------------对所有人说\n");
		printf("view$-----------------查看在线用户\n");
		printf("tran$-----------------发送文件\n");
		printf("personal$-------------私聊\n");
		printf("exit$-----------------退出\n");
		printf("=========================================\n");
		return 1;
	}
	else
		return 0;
}

//上线通知
void login_notice(struct message buf,int cfd)
{
	char info[]="来到本聊天室!";
	strcpy(buf.flag,"all");
	strcpy(buf.msg,info);
	send(cfd,&buf,sizeof(struct message),0);
}

//下线通知
void leave_notice(struct message buf,int cfd)
{
	char info[]="离开本聊天室!";
	strcpy(buf.flag,"all");
	strcpy(buf.msg,info);
	send(cfd,&buf,sizeof(struct message),0);
}



/*
 * 函数名:handlerecvmsg
 * 功能:消息接受
 * 传入参数:int *sfd
 * 返回值:无
 */
void handlerecvmsg(int *sfd)
{
	int connfd=*sfd;
	int nread;
	int fd;
	char buf[1024];
	char str[1024];
	struct message recvmsg;
	time_t timep;
	if((fd=open("chat_log.dat",O_RDWR|O_CREAT|O_APPEND,0777))<0)	//创建聊天记录文件
	{
		printf("打开聊天记录失败!\n");
		exit(1);
	}
	while(1)
	{
		nread=recv(connfd,&recvmsg,sizeof(struct message),0);//接受文件
		if(nread==0)
		{
			printf("You have detached from the server!\n");
			close(fd);
			exit(0);
		}
		else if(strcmp(recvmsg.flag,"all")==0)		//接受群发消息
		{
			time(&timep);
			memset(str,0,strlen(str));
			sprintf(str,"%s%s说:%s\n",ctime(&timep),recvmsg.name,recvmsg.msg);
			printf("%s",str);
			write(fd,str,strlen(str));
		}
		else if(strcmp(recvmsg.flag,"personal")==0)	//接收私聊消息
		{
			time(&timep);
			memset(str,0,strlen(str));
			sprintf(str,"%s%s对你说:%s\n",ctime(&timep),recvmsg.name,recvmsg.msg);
			printf("%s",str);
			write(fd,str,strlen(str));
		}
		else if(strcmp(recvmsg.flag,"tran")==0)		//文件传输
		{
				recv_file(recvmsg,connfd);
		}
		else if(strcmp(recvmsg.flag,"view")==0)		//查看在线人数
		{
			int i=0;
			printf("目前在线%d人!\n",recvmsg.size);
			for(i;i<recvmsg.size;i++)
			{
				printf("%s\n",recvmsg.woc[i]);
			}
		}
/* 		else if(strcmp(recvmsg.flag,"ask")==0)
		{
			if(strcpy(recvmsg.msg,"1")==0)
			{
				printf("文件接收成功!\n");
			}
			else
				printf("对方没有接收文件!\n");
		} */
	}
}


/*
 * 函数名:send_allpeople()
 * 功能:给所以人发送信息
 * 传入参数:struct message a, int cfd
 * 返回值:无
 */
 void send_allpeople(struct message a,int cfd)
 {
	 system("clear");
	 printf("======对所有人说=======\n");
	 printf("请输入你要说的话:\n");
	 scanf("%s",a.msg);
	 send(cfd,&a,sizeof(struct message),0);
 }
 
 
 
/*
 * 函数名:send_personal
 * 功能:私发消息
 * 传入参数:struct message a,int connfd
 * 返回值:无
 */ 
 void send_personal(struct message a,int connfd)
 {
	 system("clear");
	 printf("=========私聊===========\n");
	 printf("请输入你要聊天的对象:\n");
	 scanf("%s",a.name);
	 printf("请输入你想说的话:\n");
	 scanf("%s",a.msg);
	 send(connfd,&a,sizeof(struct message),0);
 }
 
 
 
 
 /*
 * 函数名:send_file()
 * 功能:发送文件
 * 传入参数:int cfd,char *name
 * 返回值:无
 */ 
 void send_file(int cfd,char *name)
 {
	 int fp;
	 int size;
	 int ret;
	 struct message filedata;
	 struct stat buf_st;
	 strcpy(filedata.name,name);
	 strcpy(filedata.flag,"tran");
	 strcpy(filedata.addressee,locname);
	 fp=open("./pig.txt",O_RDWR);
	 if(fp<0)
	 {
		 printf("文件打开失败!\n");
		 exit(0);
	 }
	 ret=stat("./pig.txt",&buf_st);		//获取文件的大小 保存到buf_st所指的结构体成员st_size中
	 if(ret<0)
	 {
		 perror("stat");
		 return ;
	 }
	 size=buf_st.st_size;
	 filedata.size=size;
	 send(cfd,&filedata,sizeof(filedata),0);
	 while(1)
	 {
		ret=read(fp,filedata.msg,1024);
		send(cfd,filedata.msg,ret,0);
		bzero(filedata.msg,sizeof(filedata.msg));
		if(ret!=1024)
		{
			break;
		}
	 }
	 close(fp);
	 printf("发送完成!\n");
 }
 
 
 /*
 * 函数名:recv_file()
 * 功能:接收文件
 * 传入参数:struct message msg,int cfd
 * 返回值:无
 */ 
 void recv_file(struct message msg,int cfd)
{
	int filenum1=0;
	int filenum2=0;
	int writelen=0;
	int realen=0;
	int sum=0;
	float percent=0;
	int i;
	printf("正在接收%s发来的文件....\n",msg.name);
	int fd=open("./cat.txt",O_WRONLY | O_CREAT | O_TRUNC | O_APPEND);
	if(fd<0)
	{
		perror("Receive_files open");
		return;
	}
	filenum1=msg.size/1024;
	filenum2=msg.size%1024;
	//发送应答
	send(cfd,"ACK",strlen("ACK"),0);
	
	if(filenum1==0)//小于1000
	{
		realen=recv(cfd,msg.msg,sizeof(msg.msg),0);
		writelen=write(fd,msg.msg,realen);
		bzero(msg.msg,sizeof(msg.msg));
		sum=sum+writelen;
		percent=(float)1.0*sum/msg.size;
		percent=percent*100;
		printf("完成度:%d/%d	%0.2f%c\n",sum,msg.size,percent,'%');
	}
	else if((filenum1>0)&&(filenum2==0))//BUFSIZ整数倍
	{
		for(i=0;i<filenum1;i++)
		{
			realen=recv(cfd,msg.msg,sizeof(msg.msg),0);
			writelen=write(fd,msg.msg,realen);
			bzero(msg.msg,sizeof(msg.msg));
			sum=sum+writelen;
			percent=(float)1.0*sum/msg.size;
			percent=percent*100;
			printf("完成度:%d/%d	%0.2f%c\n",sum,msg.size,percent,'%');
		}
	}
	else if((filenum1>0)&&(filenum2!=0))//BUFSIZ整数倍+多余部分
	{
		for(i=0;i<filenum1+1;i++)
		{
			realen=recv(cfd,msg.msg,sizeof(msg.msg),0);
			writelen=write(fd,msg.msg,realen);
			bzero(msg.msg,sizeof(msg.msg));
			sum=sum+writelen;
			percent=(float)1.0*sum/msg.size;
			percent=percent*100;
			printf("完成度:%d/%d	%0.2f%c\n",sum,msg.size,percent,'%');	
		}
		
	}
	printf("接收完成!\n");
	close(fd);
}
 
 

 

 

服务器:

/*
 * 聊天群服务器端
 */

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<time.h>
#include<errno.h>
#include<pthread.h>


#define PEOPLE 10		//宏定义监视的人数
#define SERVERIP	"192.168.43.229"//宏定义ip地址
#define SERVERPORT	8080	//宏定义端口号


typedef struct list	//消息结构体
{
	char flag[15];	//标志位
	char name[20];	//用户名
	char msg[1024];	//消息内容
	char addressee[20];	//传输文件目录用户
	int size;		//传输内容字节数
	struct list *next;
}LIST;
LIST *lhead=NULL;

typedef struct decr
{
	int decr;
	char name[20];
	struct decr *next;
}DECR;
DECR *phead=NULL;

struct message	//消息结构体
{
	char flag[15];	//标志位
	char name[20];	//用户名
	char msg[1024];	//消息内容
	char addressee[20];	//传输文件目录用户
	int size;		//传输内容字节数
	char woc[10][20];
};

DECR *creat_decr();
LIST *creat_list();
int add_list(char *name,char *msg);
int find_list(char *name);
int reg_check(struct message buf);
int login_check(char *name,char *msg);
int server_reg(struct message buf,int cfd);
int server_view(struct message *a);
int server_exit(int decr);
int server_login(struct message buf,int cfd);
int server_all(struct message buf,int connfd);
void server_personal(struct message a,int cfd);
void handlerecvmsg(int *sfd);
int add_decr(int decr,char *name);
int find_decr(char *name);
void find_name(int decr,struct message *a);
void send_file(struct message a,int cfd,int sfd);


int main(int argc,char *argv[])
{
	struct message buf;
	struct sockaddr_in caddr;
	struct sockaddr_in saddr;
	socklen_t addrlen=sizeof(struct sockaddr);
	int lfd;	//保存服务器套接字
	int cfd;	//保存客户端套接字
	int sfd;
	pthread_t tid=0;
	int re;
	fd_set set;
	time_t timep;
	//创建套接字
	lfd=socket(AF_INET,SOCK_STREAM,0);
	perror("socket");

	//绑定端口
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(SERVERPORT);
	saddr.sin_addr.s_addr=inet_addr(SERVERIP);
	bind(lfd,(const struct sockaddr*)&saddr,sizeof(struct sockaddr));
	perror("bind");

	//设置监听数量
	listen(lfd,PEOPLE);
	perror("listen");
	printf("正在连接....\n");


	//开始服务器程序的死循环
	while(1)
	{
		FD_ZERO(&set);
		FD_SET(lfd,&set);
		select(lfd+1,&set,NULL,NULL,NULL);
		if(FD_ISSET(lfd,&set))
		{
			cfd=accept(lfd,(struct sockaddr*)&caddr,&addrlen);
			if(cfd<0)
			{
				perror("accept");
			}
			else
			{
				recv(cfd,&buf,sizeof(buf),0);
				if(strcmp(buf.flag,"login")==0)		//客户端请求登录
				{
					add_decr(cfd,buf.name);
					server_login(buf,cfd);	//处理登录请求
					pthread_create(&tid,NULL,(void *)handlerecvmsg,(void *)&cfd);//创建线程
					pthread_detach(tid);
					continue;
				}
				else if(strcmp(buf.flag,"reg")==0)		//处理注册请求
				{
					server_reg(buf,cfd);
						
				}
			}
		}
	}
	//pthread_mutex_destory(&mutex);
	close(lfd);
	return 0;

}

//创建链表
LIST *creat_list()
{
//	return calloc(sizeof(struct list),1);
	return (LIST *) malloc(sizeof(struct list));
}


DECR *creat_decr()
{
	return (DECR *) malloc(sizeof(struct decr));
}

//添加链表
int add_list(char *name,char *msg)
{
	FILE *fp;
	LIST *p=lhead;
	if(p==NULL)
	{
		LIST *tmp=creat_list();
		p=tmp;
		lhead=tmp;
		tmp->next=NULL;
		strcpy(tmp->name,name);
		strcpy(tmp->msg,msg);
		fp=fopen("./name.dat","a+b");
		fwrite(tmp,sizeof(struct list),1,fp);
		fclose(fp);
	}
	else
	{
		while(p->next!=NULL)
		{
			p=p->next;
		}
		LIST *tmp=creat_list();
		p->next=tmp;
		strcpy(tmp->name,name);
		strcpy(tmp->msg,msg);
		tmp->next=NULL;
		fp=fopen("./name.dat","a+b");
		fwrite(tmp,sizeof(struct list),1,fp);
		fclose(fp);
	}
	return 0; 
}


//查找链表中是否有目标用户
int find_list(char *name)
{
	FILE *fp; 
	fp=fopen("./name.dat","rb");
	LIST *p=lhead;
	while(!feof(fp))
	{
		LIST *p1=creat_list();
		fread(p1,sizeof(struct list),1,fp);
		if(p==NULL)
		{
			p=p1;
			lhead=p1;
			p1->next=NULL;
		}	
		else
		{
			while(p->next!=NULL)
			{
				p=p->next;
			}
			p->next=p1;
			p1->next=NULL;
		}
	}
	p=lhead;
	while(p!=NULL)
	{
		if(strcmp(p->name,name)==0)
		{
			return 1;
			
		}
		p=p->next;
	}	
	fclose(fp);
	return 0;		//不存在返回0
}



/*
 *函数名:reg_check
 *功能:检查注册函数
 *传入参数:struct message buf
 *返回值:成功返回1;否则返回0
 */
int reg_check(struct message buf)
{
	int i;
	i=find_list(buf.name);
	if(i=1)
	{
		add_list(buf.name,buf.msg);
		return 1;
	}
	return 0;
}

/*
 * 函数名:login_check
 * 功能:检查登录用户名和密码
 * 传入参数:char *name,char *name
 * 返回值:成功返回1;否则返回0
 */
int login_check(char *name,char *msg)
{
	FILE *fp; 
	fp=fopen("./name.dat","rb");
	LIST *p=lhead;
	while(!feof(fp))
	{
		LIST *p1=creat_list();
		fread(p1,sizeof(struct list),1,fp);
		if(p==NULL)
		{
			p=p1;
			lhead=p1;
			p1->next=NULL;
		}	
		else
		{
			while(p->next!=NULL)
			{
				p=p->next;
			}
			p->next=p1;
			p1->next=NULL;
		}
	}
	p=lhead;
	while(p!=NULL)
	{
		if((strcmp(p->name,name)==0)&&(strcmp(p->msg,msg)==0))
		{
			return 1;
		}
		p=p->next;
	}
	fclose(fp);
	return 0;
}





/*
 *函数名:server_reg
 *功能:客户端注册处理
 *传入参数:struct message buf,int cfd
 *返回值:无
 */
int server_reg(struct message buf,int cfd)
{
	int i;
	i=reg_check(buf);
	if(i==1)
	{
		printf("%s注册成功!\n",buf.name);
		strcpy(buf.msg,"register,success!");
		send(cfd,&buf,sizeof(struct list),0);
	}
	else
	{
		printf("%s登录失败!\n",buf.name);
		strcpy(buf.msg,"register,failure!");
		send(cfd,&buf,sizeof(struct list),0);
	}
}



/*
 *函数名:	server_view
 *功能:	处理客户端查看当前在线用户
 *传入参数:struct message *a
 *返回值:	i
 */
int server_view(struct message *a)
{
	int i=0;
	DECR *p=phead;
	while(p!=NULL)
	{
		strcpy(a->woc[i],p->name);
		p=p->next;
		i++;
	}
	a->size=i;
	return i;
}



/*
 * 函数名:server_exit
 * 功能:处理客户端与服务器断开连接
 * 传入参数:int decr
 * 返回值:无
 */
int server_exit(int decr)
{
	DECR *p,*q,*s;
	p=phead;
	q=phead->next;
	while(q)
	{
		if(q->decr==decr)
		{
			p->next=q->next;
			s=q;
			q=q->next;
			free(s);
		}
		else
		{
			p=p->next;
			q=q->next;
		}
	}
	return 0;
}



/*
 * 函数名:server_login
 * 功能:处理客户端登录
 * 传入参数:struct message buf,int cfd
 * 返回值:无
 */
int server_login(struct message buf,int cfd)
{
	int i;
	i=login_check(buf.name,buf.msg);
	if(i==1)
	{
		printf("%s登录成功!\n",buf.name);
		memset(buf.msg,0,strlen(buf.msg));
		strcpy(buf.msg,"login,success!");
		send(cfd,&buf,sizeof(struct list),0);
		sprintf(buf.msg,"欢迎%s进入聊天室!",buf.name);
		
	}
}




/*
 * 函数名:server_personal
 * 功能:处理客户端私聊
 * 传入参数:struct message a,int cfd
 * 返回值:成功返回1,否则返回0
 */
void server_personal(struct message a,int cfd)
{
	int decr=0;
	decr=find_decr(a.name);
	find_name(cfd,&a);
	send(decr,&a,sizeof(struct message),0);
}





/*
 * 函数名:server_all
 * 功能:处理客户端群发
 * 传入参数:struct message buf,int connfd
 * 返回值:1
 */
int server_all(struct message buf,int connfd)
{
	if(strcmp(buf.msg,"")!=0)
	{
		DECR *p=phead;
		while(p!=NULL)
		{
			connfd=p->decr;
			send(connfd,&buf,sizeof(struct message),0);
			p=p->next;
		}
		
	}
}



/*
 * 函数名:handlerecvmsg()
 * 功能:   线程处理接收到客户端的命令
 * 传入参数:int *sfd
 * 返回值:
 */
void handlerecvmsg(int *sfd)
{
	int connfd=*sfd;
	int nread;
	struct message recvmsg;
	while(1)
	{
		nread=recv(connfd,&recvmsg,sizeof(struct message),0);
 		if(nread==0)
		{
			printf("You have detached from the client!\n");
			exit(0);
		} 
		if(strcmp(recvmsg.flag,"all")==0)
		{
			server_all(recvmsg,connfd);
		}
		else if(strcmp(recvmsg.flag,"view")==0)
		{
			server_view(&recvmsg);
			send(connfd,&recvmsg,sizeof(struct message),0);
		}
		else if(strcmp(recvmsg.flag,"exit")==0)
		{			
			server_exit(connfd);
			pthread_exit(NULL);
		}
		else if(strcmp(recvmsg.flag,"personal")==0)
		{
			server_personal(recvmsg,connfd);
		}
		else if(strcmp(recvmsg.flag,"tran")==0)
		{
			int cfd;
			cfd=find_decr(recvmsg.name);
			send_file(recvmsg,cfd,connfd);
		}
		else if(strcmp(recvmsg.flag,"ask")==0)
		{
			int cfd;
			cfd=find_decr(recvmsg.name);
			send(cfd,&recvmsg,sizeof(struct message),0);
		}
	}
}




/*
 * 函数名:add_decr()
 * 功能:添加套接字到链表
 * 传入参数:int decr,char *name
 * 返回值:无
 */
int add_decr(int decr,char *name)
{
	DECR *p=phead;
	if(p==NULL)
	{
		DECR *tmp=creat_decr();
		p=tmp;
		phead=tmp;
		tmp->next=NULL;
		tmp->decr=decr;
		strcpy(tmp->name,name);
	}
	else
	{
		while(p->next!=NULL)
		{
			p=p->next;
		}
		DECR *tmp=creat_decr();
		p->next=tmp;
		tmp->decr=decr;
		strcpy(tmp->name,name);
		tmp->next=NULL;
	}	
}





/*
 * 函数名:find_decr
 * 功能:查找目标人的套接字
 * 传入参数:char *name
 * 返回值:p->decr
 */
int find_decr(char *name)
{
	int i=0;
	DECR *p=phead;
	while(p!=NULL)
	{
		if((strcmp(p->name,name))==0)
		{
			i=p->decr;
			return i;
		}
		p=p->next;
	}
}


/*
 * 函数名:find_name
 * 功能:查找套接字的目标人
 * 传入参数:int decr,struct message *a
 * 返回值:无
 */
void find_name(int decr,struct message *a)
{
	DECR *p=phead;
	while(p!=NULL)
	{
		if(p->decr==decr)
		{
			strcpy(a->name,p->name);
		}
		p=p->next;
	}
}


/*
 * 函数名:send_file()
 * 功能:发送文件
 * 传入参数:struct message a,int cfd,int sfd
 * 返回值:p->decr
 */
 void send_file(struct message a,int cfd,int sfd)
 {
	 char askflag[10];
	 int filenum1=0;
	 int filenum2=0;
	 int i;
	 struct message b;
	 struct message c;
	 bzero(&b,sizeof(b));		//清理空间
	 filenum1=a.size/1000;	
	 filenum2=a.size%1000;
	 strcpy(b.name,a.addressee);
	 strcpy(b.flag,a.flag);
	 strcpy(b.addressee,a.name);
	 b.size=a.size;
	 send(cfd,&b,sizeof(b),0);
	 //等待客户端应答
/*  	while(1)
	{
		 printf("====\n");
		 recv(cfd,askflag,sizeof(askflag),0);
		 printf("%s\n",askflag);
		 if(strstr(askflag,"ACK")!=NULL)
		 {printf("123456\n");
			 break;
		 }
	} */
	 int realen=0;
	 if(filenum1==0)		//小于1000
	 {
		 bzero(b.msg,sizeof(b.msg));
		 bzero(c.msg,sizeof(c.msg));
		 realen=recv(sfd,c.msg,sizeof(c.msg),0);
		 strcpy(b.msg,c.msg);
		 send(cfd,b.msg,realen,0);
	 }
	 else if((filenum1>0) && (filenum2==0))		//整数倍
	 {
		 for(i=0;i<filenum1;i++)
		 {
			bzero(b.msg,sizeof(b.msg));
			bzero(c.msg,sizeof(c.msg));	
			realen=recv(sfd,c.msg,sizeof(c.msg),0);		
			strcpy(b.msg,c.msg);
			send(cfd,b.msg,realen,0);
		 }
	 }
	 else if((filenum1>0) && (filenum2!=0))		//整数倍+多余
	 {
		 for(i=0;i<filenum1+1;i++)
		 {
			bzero(b.msg,sizeof(b.msg));
			bzero(c.msg,sizeof(c.msg));	
			realen=recv(sfd,c.msg,sizeof(c.msg),0);
			strcpy(b.msg,c.msg);
			send(cfd,b.msg,realen,0);
		 }
	 }
	 return;
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值