5 .TCP传输 文件/数据

传文件

本质:客户端通过标准IO或者文件IO,读取文件中的信息
然后将读取到的信息,通过套接字发送给服务器
服务器接收到后,立刻通过标准IO或者文件IO写到文件

这个过程,服务器要知道2件事
1:客户端发来的文件名字
2:客户端发来的文件大小(stat函数获取)

sever.c

typedef struct Pack{
	char filename[64];
	long filesize;
}pack_t;

void read_file(int client);

int main(int argc, const char *argv[])
{
	if(argc<2){
		printf("输入port\n");
		return 1;
	}
	int port=atoi(argv[1]);
	int server=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");
	bind(server,(addr_t*)&addr,sizeof(addr));
	listen(server,10);

	int epfd=epoll_create1(EPOLL_CLOEXEC);
	struct epoll_event epoll_stdin={.events=EPOLLIN,.data.fd=0};
	struct epoll_event epoll_server={.events=EPOLLIN,.data.fd=server};
	epoll_ctl(epfd,EPOLL_CTL_ADD,0,&epoll_stdin);
	epoll_ctl(epfd,EPOLL_CTL_ADD,server,&epoll_server);
	struct epoll_event arr[50]={0};

	while(1){
		int len=epoll_wait(epfd,arr,50,-1);
		for(int i=0;i<len;i++){
			int fd=arr[i].data.fd;
			if(fd==server){
				int client=accept(server,0,0);
				printf("weclome新客户%d\n",client);
				
				struct epoll_event epoll_client={.events=EPOLLIN,.data.fd=client};
				epoll_ctl(epfd,EPOLL_CTL_ADD,client,&epoll_client);
			}
			else if(fd==0){
				char buf[64];
				scanf("%63s",buf);
				while(getchar()!=10);
				printf("stdin:%s\n",buf);
			}else{/*
				char buf[64];
				int res=read(fd,buf,64);
				if(0==res){
					printf("%d客户断开连接\n",fd);
					epoll_ctl(epfd,EPOLL_CTL_DEL,fd,0);
					close(fd);
				}else
				printf("%d消息:%s\n",fd,buf);
				*/
				read_file(fd);
			}
		}
	}
	return 0;
}
void read_file(int client){
	pack_t pack;
	read(client,&pack,sizeof(pack));//先收pack (才能打开文件)

	long filesize=pack.filesize;
	char filename[64]="server_file_system/";
	strcat(filename,pack.filename);

	int fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
	long read_size=0;
	while(1){
		char buf[1024];
		int res=read(client,buf,1024);//再收file内容
		read_size+=res;
		if(read_size>=filesize){
			printf("文件内容传输完毕\n");
			break;
		}
		write(fd,buf,res);
	}
	close(fd);
}

client.c


typedef struct Pack{
	char filename[64];
	long filesize;
}pack_t;

int main(int argc, const char *argv[])
{
	if(argc<2){
		printf("port\n");
		return 1;
	}
	int port =atoi(argv[1]);

	int client=socket(AF_INET,SOCK_STREAM,0);
	addr_in_t add;
	add.sin_family=AF_INET;
	add.sin_port=htons(port);
	add.sin_addr.s_addr=inet_addr("192.168..");

	connect(client,(addr_t*)&add,sizeof(add));
	while(1){
		pack_t pack;
		printf("filename:\n");
		scanf("%63s",pack.filename);
		while(getchar()!=10);

		int fd=open(pack.filename,O_RDONLY,0666);

		struct stat s;
		stat(pack.filename,&s);
		pack.filesize=s.st_size;
		printf("filesize=%ld B\n",pack.filesize);

		write(client,&pack,sizeof(pack));//先传pack
		while(1){
			char buf[1024];
			int res=read(fd,buf,1024);//
			write(client,buf,res);//再传file内容
			if(0==res)break;
		}
		close(fd);
	}/*
		while(1){
		char buf[64];
		printf("scanf:buf\n");
		scanf("%s",buf);
		while(getchar()!=10);
		write(client,buf,64);
		}*/
	return 0;

}

传数据

server.c

enum Type{
    TYPE_REGIST,
    TYPE_LOGIN,
    TYPE_CHAT
};
typedef struct Pack{
    enum Type type;
    char name[20];
    char pswd[20];
    char tarname[20];
    char text[1024];
} pack_t;

typedef struct User{
	char name[20];
	char pswd[20];
	//int hasmsg;
	//char msge[1024];
	int sock;
} user_t;
user_t user_arr[50] = {0};
int user_len = 0;

void insert_user(user_t user);
int find_user(const char* username);
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 = 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");
	bind(server,(addr_t*)&addr,sizeof(addr));
	listen(server,10);

	int epfd = epoll_create1(EPOLL_CLOEXEC);
	struct epoll_event epoll_stdin = {.events = EPOLLIN,.data.fd = 0};
	struct epoll_event epoll_server ={.events = EPOLLIN,.data.fd = server};
	epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &epoll_stdin);
	epoll_ctl(epfd, EPOLL_CTL_ADD, server, &epoll_server);
	struct epoll_event arr[50] = {0};

	while(1){
		int len = epoll_wait(epfd, arr, 50, -1); // 等待事件发生
		for(int i=0; i<len; i++){
			int fd = arr[i].data.fd; // 获取触发事件的文件描述符
			if(fd == server){ //服务端socket有新连接
				int client = accept(server, 0, 0); 
				printf("%d客户端连接\n",client);
				struct epoll_event epoll_client = {.events = EPOLLIN,.data.fd = client};
				epoll_ctl(epfd, EPOLL_CTL_ADD, client, &epoll_client); 
			} else if(fd == 0){ // 标准输入
				char buf[64];
				scanf("%63s", buf);
				while(getchar() != '\n'); 
				printf("键盘输入数据:%s\n", buf);
			} else{ // 客户端发送的数据
				read_data(fd);// 处理文件或网络数据的读取
			}
		}
	}
	return 0;
}
void insert_user(user_t user){
	user_arr[user_len] = user;
	user_len++;
}
int find_user(const char* username){
	for(int i=0;i<user_len;i++)
        if(strcmp(username,user_arr[i].name) == 0)
            return i;
    return -1;
}

void read_data(int client){  
	//while(1){
	pack_t pack ;  
	read(client,&pack,sizeof(pack));///  
	int res = find_user(pack.name);// 根据用户发来的账号,在数组中查询是否存在  
	char* msg = NULL;  

	switch(pack.type){  
	case TYPE_REGIST:{ 
						 if(res == -1){// 不存在  
							 user_t user;  
							 strcpy(user.name,pack.name);  
							 strcpy(user.pswd,pack.pswd);  
							 insert_user(user);  
							 msg = "注册成功";  
						 }else
							 msg = "该账号已存在";  

						 strcpy(pack.text,msg);  
						 write(client,&pack,sizeof(pack));///
						 break;  
					 }
	case TYPE_LOGIN:{
						if(res == -1)  
							msg = "该账号不存在";  
						else{  
							user_t user = user_arr[res];// 将找到的用户单独拎出来  
							if(strcmp(user.pswd,pack.pswd) == 0){  
								msg = "登录成功";  
								user_arr[res].sock = client;  
								/*
								   if(user_arr[res].hasmsg){
								   pack_t pack={0};
								   pack.type=TYPE_CHAT;
								   strcpy(pack.text,user_arr[res].msge);
								   write(client,&pack,sizeof(pack));///
								   user_arr[res].hasmsg=0;
								   }*/
							}else  
								msg =" 密码错误";  
						}  
						strcpy(pack.text,msg);  
						write(client,&pack,sizeof(pack)); /// 
						break;  
					}
	case TYPE_CHAT:{
					   if(res == -1){
						   msg = "用户不存在";

						   strcpy(pack.text, msg);
						   write(client, &pack, sizeof(pack));///
					   }else{
						   user_t user = user_arr[res];
						   if(user.sock == 0){
							   msg = "用户未登录";
							   /*user_arr[res].hasmsg=1;
								 strcpy(user_arr[res].msge,pack.text);*/

							   strcpy(pack.text, msg);
							   write(client, &pack, sizeof(pack));///
						   }else{// 用户登录
							   int tarsock = user.sock;
							   write(tarsock, &pack, sizeof(pack));///
						   }
					   }
					   break;
				   }
	}
}

client.c

enum Type{
	TYPE_REGIST,
    TYPE_LOGIN,
    TYPE_CHAT
};
typedef struct Pack{
    enum Type type;
    char name[20];
    char pswd[20];
    char tarname[20];
    char text[1024];
}pack_t;

void* thread_main(void* arg){//后台read(client)
	int client = *(int*)arg;  
	while(1){  
		pack_t pack = {0};  
		int res = read(client,&pack,sizeof(pack));///r
		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_CHAT:  
			printf("接收到消息:%s\n",pack.text);  
			break;  
		}  
	}  
}  
int main(int argc, const char *argv[]){//前台write(client)
	if(argc != 2){
		printf("请输入端口号\n");
		return 1;
	}
	int port = atoi(argv[1]);
	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..");
	connect(client,(addr_t*)&addr,sizeof(addr));

	pthread_t id;
	pthread_create(&id, 0, thread_main, &client);
	pthread_detach(id);

	while (1) {
		int ch = -1;
		printf("1:注册\n");
		printf("2:登录\n");
		printf("3:聊天\n");
		printf("0:退出\n");
		printf("请选择:");
		scanf("%d", &ch);
		while (getchar() != 10);   
		pack_t pack;
		switch (ch) {
		case 1: 
			pack.type = TYPE_REGIST;
			printf("请输入账号:");
			scanf("%s", pack.name);
			while (getchar() != 10);
			printf("请输入密码:");
			scanf("%s", pack.pswd);
			while (getchar() != 10);
			write(client, &pack, sizeof(pack));///w
			break;
		case 2: 
			pack.type = TYPE_LOGIN;
			printf("请输入账号:");
			scanf("%s", pack.name);
			while (getchar() != 10);
			printf("请输入密码:");
			scanf("%s", pack.pswd);
			while (getchar() != 10);
			write(client, &pack, sizeof(pack));///w
			break;
		case 3: 
			// 聊天对象的姓名放在pack.tarname里面
			// 聊天内容放在 pack.text 里面
			// 例如:张三 你好
			pack.type = TYPE_CHAT;
			scanf("%s %s", pack.tarname, pack.text);
			while(getchar() != '\n');
			//printf("tarname = %s\n", pack.tarname);
			write(client, &pack, sizeof(pack));///w
			break;
		case 0:
			break;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值