【无标题】

客户端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/epoll.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;	

int find_name(const char* name);

enum Type
{
	TYPE_REGIST,
	TYPE_LOGIN,
	TYPE_CHAR,
	TYPE_FILE_OUT
};
typedef struct pack_t{
	enum Type type;
	char name[20];
	char pswd[20];
	char filename[64];
	long filesize;
	char ownname[20];
	char text[1024];
}pack_t;
typedef struct user_t{
	char user_name[20];
	char user_pswd[20];
	int user_sock_fd;
	int flagMsg;
	char Msg[1024];
	int flagFile;
	char fname[64]; //文件在服务器的文件名地址
	char file_name[64];//源文件名
}user_t;

user_t user[50] = {0};
int len = 0;
void add_name(user_t own);
void read_data(int client);
int main(int argc, const char *argv[])
{
	if(argc < 2)
	{
		printf("请输入端口号\n");
		return -1;
	}
	int port = atoi(argv[1]);
	int server_fd = socket(AF_INET,SOCK_STREAM,0);//创造服务器套接字
	
	addr_in_t addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");
	if(bind(server_fd,(addr_t*)&addr,sizeof(addr)) == -1)//将要接受信息的IP和port写入服务器套接字,并判断是否写入成功
	{
		perror("bind");
		return -1;
	}

	listen(server_fd,10);//监听,创造监听列表,将监听到的客户端存入监听列表中

	int epfd = epoll_create1(EPOLL_CLOEXEC); //创造一个动态的监视列表,并返回该列表的文件描述符
	struct epoll_event server_event = {.events=EPOLLIN,.data.fd=server_fd};
	epoll_ctl(epfd,EPOLL_CTL_ADD,server_fd,&server_event); //将服务器套接字描述符以监视是否可读的形式写入监视列表
	struct epoll_event stdin_event = {.events=EPOLLIN,.data.fd=0};
	epoll_ctl(epfd,EPOLL_CTL_ADD,0,&stdin_event);//将标准输入流的描述符写入监听列表

	struct epoll_event arr[64] = {0}; //创造一个用来保存已被激活的描述符

	while(1)
	{
		int size = epoll_wait(epfd,arr,64,-1); //监视有多少个描述符被激活,接收被激活的个数,并将激活的描述符存入到arr结构体数组中
		for(int i=0;i<size;i++)
		{
			if(arr[i].events != EPOLLIN) //如果该描述符不是以可读的形式被激活的,那么久跳出当前循环
			{
				continue;
			}
			int fd = arr[i].data.fd;
			if(fd == server_fd) //有客户端连接服务器
			{
				int client_fd = accept(server_fd,0,0); //接收客户端的连接并返回该客户端套接字在服务器中的描述符
				printf("有客户端连接\n");
				struct epoll_event client_event = {.events=EPOLLIN,.data.fd=client_fd};
				epoll_ctl(epfd,EPOLL_CTL_ADD,client_fd,&client_event); //将接收到的客户端套接字的描述符存入到监视列表中
			}
			else if(fd == 0) //标准输入流有可读取的内容(键盘敲入数据)
			{
				char buf[64] = "";
				scanf("%s",buf);      //读取标准输入流的数据
				while(getchar()!=10); //吸收在缓存区多余的数据
				printf("标准输入流的数据为:%s\n",buf);
			}
			else //客户端有发来数据
			{
				read_data(fd);
				
			}
		}
	}
	return 0;
}
int find_name(const char* name)
{
	for(int i=0; i<len; i++)
	{
		if(strcmp(name,user[i].user_name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void add_name(user_t own)
{
	user[len] = own;
	len++;
}
void read_data(int client)
{
	pack_t pack = {0};
	int res = read(client,&pack,sizeof(pack));
	
	switch(pack.type)
	{
		case TYPE_REGIST:
			{
			char* msg = NULL;
			int flag = find_name(pack.name);
			if(flag == -1)
			{
				user_t own = {0};
				strcpy(own.user_name,pack.name);
				strcpy(own.user_pswd,pack.pswd);
				add_name(own);
				msg = "创建成功";
			}
			else
			{
				msg = "创建失败\n";
			}
			strcpy(pack.text,msg);
			write(client,&pack,sizeof(pack));
			break;
			}
		case TYPE_LOGIN:
			{
			char* msg = NULL;
			int flag = find_name(pack.name);
			if(flag == -1)
			{
				msg = "没有此用户";
			}
			else
			{
				user_t user1 = user[flag];
				if(strcmp(user1.user_pswd,pack.pswd) == 0)
				{
					msg = "登录成功";
					user[flag].user_sock_fd = client;
					if(user[flag].flagMsg == 1)
					{
						pack_t pack = {0};
						pack.type = TYPE_CHAR;
						strcpy(pack.text,user[flag].Msg);
						write(client,&pack,sizeof(pack));
						user[flag].flagMsg = 0;

					}
					if(user[flag].flagFile == 1)
					{
						pack_t pack = {0};
						pack.type = TYPE_FILE_OUT;
						int fd = open(user[flag].fname,O_RDONLY);
						struct stat stat_buf = {0};
						stat(user[flag].fname,&stat_buf);
						long len = stat_buf.st_size;
						strcpy(pack.filename,user[flag].file_name);
						pack.filesize=len;
						write(client,&pack,sizeof(pack));
						long read_size = 0;
						while(1)
						{
							memset(pack.text,0,sizeof(pack.text));
							
							read(fd,&pack,sizeof(pack));
							int read = strlen(pack.text);
							read_size += read;
							write(client,&pack,sizeof(pack));
							if(read_size >= len)
							{
								break;
							}
						}
						close(fd);
						user[flag].flagFile == 0;
					}
				}
				else
				{
					msg = "密码错误";
				}
				
			}
				strcpy(pack.text,msg);
				write(client,&pack,sizeof(pack));
			break;
			}
		case TYPE_CHAR:
			{
			char* msg = NULL;
			int flag = find_name(pack.ownname);
			if(flag == -1)
			{
				msg = "没有此用户";
			}
			else
			{
				int sock = user[flag].user_sock_fd;
				if(sock == 0)
				{
					msg = "该用户没登录";
					user[flag].flagMsg = 1;
					strcpy(user[flag].Msg,pack.text);
				}
				else
				{
					write(sock,&pack,sizeof(pack));
					msg = "发送成功";
				}

			}

				strcpy(pack.text,msg);
				write(client,&pack,sizeof(pack));
			break;
			}
		case TYPE_FILE_OUT:
			{
				char* msg = NULL;
				int flag = find_name(pack.ownname);
				if(flag == -1)
				{
					msg = "没有该用户";
				}
				else
				{ 
					if(user[flag].user_sock_fd == 0)
					{
						msg = "该用户处于离线状态";
						strcpy(user[flag].file_name,pack.filename);
						char filename[64] = "./server/" ;
						strcpy(filename,pack.filename);
						strcpy(user[flag].fname,filename);
						user[flag].flagFile = 1;
						int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664); 
						long len = pack.filesize;
						long readed_size = 0;
						while(1)
						{
							memset(pack.text,0,sizeof(pack.text));
							read(client,&pack,sizeof(pack));
							printf("消息存入本地中\n");
							int read = strlen(pack.text);
							write(fd,pack.text,read);
							readed_size += read;
							if(readed_size >= len)
							{
								break;
							}
						}
						close(fd);
					}
					else
					{
						while(1)
						{
							printf("服务器接收中\n");
							read(user[flag].user_sock_fd,&pack,sizeof(pack));
						}
					}

				}
			}
	}
}

客户端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

enum Type
{
	TYPE_REGIST,
	TYPE_LOGIN,
	TYPE_CHAR,
	TYPE_FILE_OUT
};
typedef struct pack_t{
	enum Type type;
	char name[20];
	char pswd[20];
	char filename[64];
	long filesize;
	char ownname[20];
	char text[1024];
}pack_t;

void* thread_main(void* arg){
	int client =*(int*)arg;
	while(1){
		pack_t pack ={0};
		int res = read(client,&pack,sizeof(pack));
		if(res ==0){break;}
		switch(pack.type){
				case TYPE_REGIST:
					printf("%s\n",pack.text);
					break;
				case TYPE_LOGIN:
					printf("%s\n",pack.text);
					break;
				case TYPE_CHAR:
					printf("%s\n",pack.text);
					break;
				case TYPE_FILE_OUT:
					{

						char filename[64] = "./client/" ;
						strcpy(filename,pack.filename);
						long len = pack.filesize;
						int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
						long read_size = 0;
						while(1)
						{
							memset(pack.text,0,sizeof(pack.text));
							read(client,&pack,sizeof(pack));
							int read = strlen(pack.text);
							read_size += read;
							write(fd,pack.text,strlen(pack.text));
							printf("接收中\n");
							if(read_size >= len)
							{
								break;
							}

						}
						close(fd);

					}
			   }
			}
}
int main(int argc, const char *argv[])
{
	if(argc !=2 ){
		printf("请输入端口号\n");
		return 1;
	}
	// ./server 8888
	int port = atoi(argv[1]);// 将字符串 8888 转换成int类型port


	int client = socket(AF_INET,SOCK_STREAM,0);
	addr_in_t addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("192.168.127.129");

	if(connect(client,(addr_t*)&addr,sizeof(addr)) == -1){
		perror("connect");
		return 1;
	}
	pthread_t id;
	pthread_create(&id,0,thread_main,&client);
	pthread_detach(id);
	while(1)
	{
		int flag;
		printf("1.注册\n");
		printf("2.登录\n");
		printf("3.发送消息\n");
		printf("4.发送文件\n");
		printf("5.退出\n");
		printf("请输入:");
		scanf("%d",&flag);
		switch(flag)
		{
			case 1:
				{
				pack_t pack = {0};
				pack.type = TYPE_REGIST;
				printf("请输入新账号:");
				scanf("%s",pack.name);
				printf("请输入密码:");
				scanf("%s",pack.pswd);
				write(client,&pack,sizeof(pack));
				break;
				}
			case 2:
				{
				pack_t pack = {0};
				pack.type = TYPE_LOGIN;
				printf("请输入账号:");
				scanf("%s",pack.name);
				printf("请输入密码:");
				scanf("%s",pack.pswd);
				write(client,&pack,sizeof(pack));
				break;
				}
			case 3:
				{
				pack_t pack = {0};
				pack.type = TYPE_CHAR;
				printf("请输入被发送人账号以及内容\n");
				scanf("%s %s",pack.ownname,pack.text);
				write(client,&pack,sizeof(pack));
				break;
				}
			case 4:
				{
					pack_t pack = {0};
					pack.type = TYPE_FILE_OUT;
					printf("请输入被发送人的账号:");
					scanf("%s",pack.ownname);
					while(getchar()!= 10);
					printf("请输入文件名:");
					scanf("%s",pack.filename);
					int fd = open(pack.filename,O_RDONLY);
					if(fd == -1)
					{
						printf("没有该文件\n");
						return -1;
					}
					struct stat stat_buf = {0};
					stat(pack.filename,&stat_buf);
					pack.filesize = stat_buf.st_size;
					write(client,&pack,sizeof(pack));
					long readed_size = 0;
					while(1)
					{
						memset(pack.text,0,sizeof(pack.text));
						read(fd,&pack,sizeof(pack));
						int read = strlen(pack.text);
						write(client,&pack,sizeof(pack));
						printf("文件传输中\n");
						if(readed_size >= pack.filesize)
						{
							break;
						}
					}
				}
			case 5:exit(0);

		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值