linux c开发并发词典server与client

linux c多线程技术开发并发词典查询server与client

server与client功能说明

使用多线程并发技术实现服务端程序,解析所有客户端请求与回复,客户端功能有登录,注册,查单词,历史查询记录查询(功能可扩展,词库采用(key vaule形式).txt格式村存储)

忠告

这不是优秀的代码手编写,各路高手请勿多多关照,代码有好有坏的地方,有什么问题还望各路高手指出,技术无限,分享精神有限 ------纯原创,转载请说明出处(代码不止我这一版但是其他的很多都需要积分下载)

下面开始代码正文

dict_server.c.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<pthread.h>
#include<time.h>
typedef struct cliinfo{
	int cli_fd;//客户端连接后操作符
	struct sockaddr_in cliaddr;//保存连接客户端信息
} CLIINFO;
void* connect_client(void* arg)
{
	CLIINFO *info = (CLIINFO *)arg;
	char ip[16];
	memset(ip,0,16);
	printf("client : ip = %s port = %d\n",inet_ntop(AF_INET,&(info->cliaddr.sin_addr.s_addr),ip,16),ntohs(info->cliaddr.sin_port));//打印连接客户端信息
	char buf[1024];
	char fdbuf[1024];
	int flag = 0;
	int ret = -1;
	while(1)
	{
		start:
		flag = 0;
		ret = -1;
		memset(buf,0,sizeof(buf));
		ret = read(info->cli_fd,buf,sizeof(buf));
		if(ret < 0)
		{
			perror("read");
			break;
		}
		else if(ret == 0)//客户端退出检测
		{
			printf("ip : %s client close\n",inet_ntop(AF_INET,&(info->cliaddr.sin_addr.s_addr),ip,16));
			break;
		}
		//登录认证(打开用户信息文件读取进行查询)
		//int fd = open("/home/unix-hjl/userinfo.txt",O_RDONLY);
		FILE *file = NULL;
		file = fopen("/home/unix-hjl/userinfo.txt", "r+");
		
		if(file == NULL)
		{
			break;
		}
		else
		{
			while(!feof(file))
			{
				memset(fdbuf,0,sizeof(fdbuf));
				fgets(fdbuf,sizeof(fdbuf),file);
				if(strncmp(fdbuf,buf,strlen(buf)) == 0)
				{
					write(info->cli_fd,"yes",3);//回写登录成功标志
					fclose(file);//关闭文件描述符
					printf("login \n");
					flag = 1;//登录成功标志置 1
					break;
				}
			}
			if(flag != 1)
			{
				if(strncmp(buf,"3",1) == 0)
				{
					//执行注册
					memset(buf,0,sizeof(buf));
					read(info->cli_fd,buf,sizeof(buf));
					fwrite(buf,1,strlen(buf),file);
					char h_str[64];
					char name[16];
					memset(h_str,0,sizeof(h_str));
					memset(name,0,sizeof(name));
					int x = 0;
					for(x; buf[x] != ' '; ++x)
					{
						name[x] = buf[x];
					}
					sprintf(h_str,"%s%s",name,"_historyfind.txt");
					FILE *f = fopen(h_str,"w+");//创建历史记录文件
					if(f == NULL)
					{
						printf("创建文件失败!!!\n");
					}
					write(info->cli_fd,"1",1);
					fclose(f);
					fclose(file);
					goto start;
				}
				else
				{
					write(info->cli_fd,"no",3);//回写登录失败标志
				}
				
			}
			if(flag)
			{
				char path_str[64];
				char name_str[16];
				memset(path_str,0,sizeof(path_str));
				memset(name_str,0,sizeof(name_str));
				int x = 0;
				for(x; buf[x] != ' '; ++x)
				{
					name_str[x] = buf[x];
				}
				sprintf(path_str,"%s%s%s","/home/unix-hjl/",name_str,"_historyfind.txt");
				FILE *user_fd = fopen(path_str,"r");
				if(file == NULL)
				{
					perror("open");
					break;
				}
				while(!feof(file))
				{
					memset(fdbuf,0,sizeof(fdbuf));
					fgets(fdbuf,sizeof(fdbuf),user_fd);
					write(info->cli_fd,fdbuf,strlen(fdbuf));//回写历史记录
					
				}
				usleep(5000);
				write(info->cli_fd,"endl",4);//回写结束
				fclose(user_fd);
				while(1)
				{
					//进入查询
					memset(buf,0,sizeof(buf));
					ret = read(info->cli_fd,buf,sizeof(buf));
					if(ret == 0)//客户端退出检测
					{
						printf("client ip : %s close\n",inet_ntop(AF_INET,&(info->cliaddr.sin_addr.s_addr),ip,16));
						pthread_exit(NULL);
					}
					if(strncmp(buf,"quitlogin",9) == 0)
					{
						printf("quit login\n");//退出查询
						break;
					}
					file = fopen("/home/unix-hjl/dict.txt","r");
					if(file == NULL)
					{
						perror("open");
						break;
					}
					char cmp_str[32];
					while(!feof(file))
					{
						memset(cmp_str,0,sizeof(cmp_str));
						memset(fdbuf,0,sizeof(fdbuf));
						fgets(fdbuf,sizeof(fdbuf),file);
						int i = 0;
						for(i; (fdbuf[i] != ' ') && (strlen(fdbuf)) ; ++i)
						{
							cmp_str[i] = fdbuf[i];
						}
						int len = strlen(buf) - 1;
						if((strncmp(cmp_str,buf,i) == 0) && ( i == len))
						{
							write(info->cli_fd,fdbuf,strlen(fdbuf));//回写查询记录
							FILE *fd = fopen(path_str,"a+");
							fwrite(fdbuf,1,strlen(fdbuf),fd);//向文件写入查询记录
							usleep(1000);//延时,避免粘包导致异常
							write(info->cli_fd,"endl",4);//回写结束
							fclose(fd);
							flag = 0;
							break;
						}
					}
					if(flag != 0)
					{
						write(info->cli_fd,"2",1);//未查询到
					}
					usleep(100);
					flag = 1;
					fclose(file);//关闭文件描述符
				}
			}
		}
	}
	close(info->cli_fd);
	free(info);
}

int main(int argc,char *argv[])
{ 
	if(argc < 3)
	{
		fprintf(stderr,"USER:%s IP PORT",argv[0]);
		return -1;
	}
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
	int ret = -1;
	int sock_fd = -1;
	
	//1、创建socket套接字 AF_INET SOCK_STREAM
	sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if(sock_fd < 0)
	{
		perror("socket error");
		exit(-1);
	}
	//2、绑定bind
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;//设置地址族
	addr.sin_port = htons(atoi(argv[2]));//设置端口
	inet_pton(AF_INET,argv[1],&addr.sin_addr.s_addr);//设置IP
	ret = bind(sock_fd,(struct sockaddr *)&addr,sizeof(addr));
	if(ret < 0)
	{
		perror("socket error");
		exit(-1);
	}
	//2、监听
	ret = listen(sock_fd,128);
	if(ret < 0)
	{
		perror("listen error");
		exit(-1);
	}
	struct sockaddr_in cliaddr;
	socklen_t len = sizeof(cliaddr);
	CLIINFO *info;
	while(1)
	{
		//3、提取
		int cli_fd = accept(sock_fd,(struct sockaddr *)&cliaddr,&len);
		if(cli_fd < 0)
		{
			perror("accept error");
			exit(-1);
		}
		pthread_t pthid;
		info = malloc(sizeof(CLIINFO));
		info->cli_fd = cli_fd;
		info->cliaddr = cliaddr;
		pthread_create(&pthid,&attr,connect_client,info);

	}
	//6、关闭连接
	close(sock_fd);
	return 0;
}

dict_client.c.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
/*
   说明:
   	历史记录每次登录时直接显示
*/
//1、登录认证
int login(char *user_arg, int fd)
{
   char buf[1024];
   memset(buf,0,sizeof(buf));
   write(fd,user_arg,strlen(user_arg));
   int ret = read(fd,buf,sizeof(buf));
   if(ret < 0)
   {
   	perror("read");
   	return -1;//System Error
   }
   else if(strncmp(buf,"yes",3) == 0)
   {
   	return 0;//登录成功
   }
   return 1;//登录失败
}
//2、登录历史查询记录回显
int display_history(int fd)
{
   
   char buf[1024];
   memset(buf,0,sizeof(buf));
   while(1)
   {
   	//printf("debug-1\n");//测试点
   	memset(buf,0,sizeof(buf));
   	int ret = read(fd,buf,sizeof(buf));
   	if(ret < 0)
   	{
   		perror("read");
   		return -1;//System Error
   	}
   	else if((ret > 0) && (strncmp(buf,"endl",4) != 0))
   	{
   		write(STDOUT_FILENO,buf,strlen(buf));//显示历史查询记录
   	}
   	else
   	{
   		printf("\n");
   		break;//收到结束标志,结束读取
   	}
   }
   return 0;
}
//3、查询单词
int fandByDict(char *word,int fd)
{
   char buf[1024];
   write(fd,word,strlen(word));
   while(1)
   {
   	memset(buf,0,sizeof(buf));
   	int ret = read(fd,buf,sizeof(buf));
   	if(ret < 0)
   	{
   		perror("read");
   		return -1;//System Error
   	}
   	else if((ret > 0) && ((strncmp(buf,"endl",4) != 0)))
   	{
   		if(strcmp(buf,"2") == 0)
   		{
   			printf("%s",buf);
   			return 2;//未查到单词
   		}
   		write(STDOUT_FILENO,buf,strlen(buf));
   	}
   	else
   	{
   		break;//收到结束标志,结束读取
   	}
   }
   return 0;
}

//4、注册账户
int register_account(char *info,int fd)
{
   write(fd,"3",1);
   char buf[1024];
   memset(buf,0,sizeof(buf));
   write(fd,info,strlen(info));
   usleep(100);
   memset(buf,0,sizeof(buf));
   read(fd,buf,sizeof(buf));
   if(strncmp(buf,"1",1) == 0)
   {
   	return 0;//注册成功
   }
   return 1;//注册失败
}
//tcp客户端
int main(int argc, char *argv[])
{
   if(argc < 3)
   {
   	fprintf(stderr,"USER:%s IP PORT",argv[0]);
   	return -1;
   }
   int sock_fd = -1;
   int ret = -1;
   //1、创建socket套接字 AF_INET SOCK_STREAM
   sock_fd = socket(AF_INET,SOCK_STREAM,0);
   if(sock_fd < 0)
   {
   	perror("socket error");
   	exit(1);
   }
   //2、建立连接 connect
   struct sockaddr_in addr;
   addr.sin_family = AF_INET;
   addr.sin_port = htons(atoi(argv[2]));
   inet_pton(AF_INET,argv[1],&addr.sin_addr.s_addr);
   ret = connect(sock_fd,(struct sockaddr *)&addr,sizeof(addr));
   if(ret < 0)
   {
   	perror("connect error");
   	exit(1);
   }
   char buf[1024];
   while(1)
   {
   	int n = 3;
   	int count = 0;//登录n次失败将推出客户端

   	memset(buf,0,sizeof(buf));
   	printf("1、退出客户端请输入:quitfind\n2、登录请输入:login\n3、注册请输入:register请输入选择:\n");
   	fgets(buf,sizeof(buf),stdin);
   	if(strncmp(buf,"quitfind",8) == 0)
   	{
   		break;//退出查询
   	}
   	if(strncmp(buf,"register",8) == 0)//注册账号
   	{
   		printf("请输入账号和密码(格式 name pwd):\n");
   		fgets(buf,sizeof(buf),stdin);
   		ret = register_account(buf,sock_fd);
   		if(ret == 0)
   		{
   			printf("注册账号成功!!!\n");
   			memset(buf,0,sizeof(buf));
   		}
   	}
   	if(strncmp(buf,"login",5) == 0)
   	{
   		login:
   		printf("请输入账号密码(格式为name pwd):\n");
   		memset(buf,0,sizeof(buf));
   		fgets(buf,sizeof(buf),stdin);
   		if(login(buf,sock_fd) == 0)
   		{
   			printf("登录成功!!!\n");//登录成功
   			printf("历史查询记录:\n");
   			display_history(sock_fd);//显示历史记录
   			while(1)
   			{
   				//printf("debug\n");
   				memset(buf,0,sizeof(buf));
   				printf("请输入需要查询的单词(输入 quitlogin 退出登录):\n");
   				fgets(buf,sizeof(buf),stdin);
   				if(strncmp(buf,"quitlogin",9) == 0)
   				{
   					write(sock_fd,"quitlogin",9);
   					usleep(100);
   					break;//退出查询
   				}
   				ret = fandByDict(buf,sock_fd);
   				if(ret == 2)
   				{
   					printf("未搜索到单词:%s\n",buf);
   				}
   			}
   		}
   		else
   		{
   			++count;
   			printf("第:%d 次登录失败,还可尝试 %d 次后将推出程序!!!\n",count,n-count);
   			if(count == n)
   			{
   				break;//登录失败,退出客户端
   			}
   			goto login;
   		}
   	}
   	printf("%s",buf);
   }
   //5、关闭连接
   close(sock_fd);
   return 0;
}

纯原创,转载请说明出处(分享给需要的盆友们)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值