Linux下 Socket服务器和客户端文件互传

news2024/11/26 4:40:33

目录

1.项目描述

2.函数准备

2.1 gets函数

2.2 popen函数、fread函数

 2.3 access 函数

 2.4 exit 函数

 2.5 strtok 函数

2.6 chdir函数

3.项目代码

3.1服务器代码

3.2客户端代码

4.问题总结


1.项目描述

基于Soket聊天服务器,实现服务器和客户端的文件传输。

Linux系统下建立Socket聊天服务器_趣知boy的博客-CSDN博客

ls   获取服务器文件列表   
pwd  获取服务器当前路径
cd   对服务器目录的操作  +dir
quit 退出连接  

put 上传文件到服务器  +file_name
get 获取服务器数据    +file_name

lcd 对客户端目录的操作 +dir
lls 列出客户端所有文件 

       
dofile 创建文件  

项目结构

2.函数准备

2.1 gets函数

gets 从标准输入流(通常是键盘)读取一行字符串,并将其存储在指定的字符数组中。

其比较重要的一个功能是阻塞

   printf("请输入您的姓名:");
   gets(name);
   printf("您的姓名是:%s\n", name);

2.2 popen函数、fread函数

size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

 该函数可以读取指定数量(count = 1)的元素,每个元素的大小为size个字节,从指定文件(stream)中读取到内存指针(ptr)所指的位置。 

 2.3 access 函数

用于判断文件或目录是否具有某种权限。

int access(const char *pathname, int mode);
F_OK:检查文件是否存在
R_OK:检查读权限是否存在
W_OK:检查写权限是否存在
X_OK:检查执行权限是否存在

返回值:

  • 如果路径名指定的文件或目录具有所需的权限,则返回0。

  • 如果权限不足,则返回-1,并且errno设置为适当的错误码

 2.4 exit 函数

exit函数是一个用于终止程序运行的函数。当调用exit函数时,程序将立即退出并返回到操作系统。

 2.5 strtok 函数

char *strtok(char *str, const char *delim);

 其中str是要进行分割的字符串,delim是作为分隔符的字符串。函数返回一个指向被分割出的子字符串的指针。

strtok函数陷阱:会改变指针指向的字符串,所以想保留原来str需要用strcpy复制出来处理。

token = strtok(str, ",");
while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ",");
}
 
return 0;

执行上述代码会输出以下结果:

Hello

World

This

is

Strtok

2.6 chdir函数

更改当前工作目录

int chdir(const char *path);

参 数:Path 目标目录,可以是绝对目录或相对目录。

返回值:成功返回0 ,失败返回-1

3.项目代码

3.1服务器代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "config.h" 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

struct Msg msg;
int ss_fd;

void handler_cmd(char *cmd){
	int cmd_int,fd;
	char *p;
	FILE *file;
	char *cmd_pre=cmd;
	//handle the cmd to number
	if(!strcmp(cmd_pre,"ls")) cmd_int=ls;
	if(!strcmp(cmd_pre,"pwd")) cmd_int=pwd;  
    if(!strcmp(cmd_pre,"quit")) cmd_int=quit;
    if(!strcmp(cmd,"lls"))      cmd_int=lls;
    
    if(strstr(cmd,"lcd")!=NULL) cmd_int=lcd;
    
    if(strstr(cmd_pre,"cd")!=NULL) cmd_int=cd;
    if(strstr(cmd_pre,"put")!=NULL) cmd_int=put;
    if(strstr(cmd_pre,"get")!=NULL) cmd_int=get;
    
	//handle cmd 
    switch(cmd_int){
		case ls:
		case pwd:
			file=popen(cmd,"r");
			fread(msg.data,sizeof(msg.data),1,file);
			printf("%s",msg.data);
			write(ss_fd,&msg,sizeof(msg));
			break;
		case cd:
			p=strtok(cmd," ");
			p=strtok(NULL," ");
			printf("dir:%s \r\n",p);
			strcpy(msg.data,"change dir over \r\n");
			write(ss_fd,&msg,sizeof(msg));   //must give a msg back
			chdir(p);
			break;
		case get:
			p=strtok(cmd," ");
			p=strtok(NULL," ");
			printf("dir:%s \r\n",p);	
			if(!access(p,F_OK)){  //if have this file
				msg.flag=dofile;
				fd=open(p,O_RDONLY);
				read(fd,&msg.data,sizeof(msg.data));
				send(ss_fd,&msg,sizeof(msg),0);
				close(fd);
			}else{   //if no this file
				send(ss_fd,"no this file \r\n",16,0);
			}
			break;
		case put:
			p=strtok(cmd," ");
			p=strtok(NULL," ");
			printf("dir:%s \r\n",p);
			fd=open(p,O_RDWR|O_CREAT,0666);
			write(fd,&msg.data,strlen(msg.data));
			close(fd);
			
			strcpy(msg.data,"i have got a file.\r\n");
			write(ss_fd,&msg,sizeof(msg));   //must give a msg back
			
			break;
		case quit:
			msg.flag=quit;
			printf("quit==========\r\n");
			exit(-1);
			
	}
    
}

int main(void)
{
	int s_fd,nread,len;

	struct sockaddr_in s_ddr;  //build server msg
	struct sockaddr_in c_ddr;  //save clinet msg

	s_fd= socket(AF_INET, SOCK_STREAM, 0);//1.build a soket specified
	if(s_fd==-1){
		perror("error is");
	}
	//2.build all bind
	s_ddr.sin_family=AF_INET;
	s_ddr.sin_port=htons(8880);
	s_ddr.sin_addr.s_addr=htonl(INADDR_ANY);
	//give the bind
	bind(s_fd,(struct sockaddr *)&s_ddr,sizeof(s_ddr));
	//3.waite for client
	listen(s_fd,8);
	//4.accept come and connect for once
	len=sizeof(c_ddr);
	while(1){
		ss_fd=accept(s_fd,(struct sockaddr *)&c_ddr,&len);
		if(ss_fd == -1){
			perror("accept:");
		}
		printf("conect succese!==========\r\n");
		//5.read from connect ss_fd
		if(fork()==0){   //creat kid pid for handler msg and cmd 
			
			//5.2 read	
			while(1){
				memset(&msg,'\0',sizeof(msg));   //clear msg
				printf("====================\r\n");
				nread=read(ss_fd,&msg,sizeof(msg));
				if(nread==0){                 // cannot recv cmd 
					printf("connect is cutdon! \r\n");
					break;
				}else{                        //can recive cmd 
					printf("server  receved  cmd:%s \r\n",msg.cmd); 
					printf("====================\r\n");
					handler_cmd(msg.cmd);    //hander the cmd  give msg data		
				}
			}
			
		}

	}
	close(ss_fd);
	close(s_fd);
	return 0;
}

3.2客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "config.h" 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int cmd_to_number(char *cmd)
{
	if(!strcmp(cmd,"ls")) return ls;
	if(!strcmp(cmd,"pwd")) return pwd;  
    if(!strcmp(cmd,"quit")) return quit;
    if(!strcmp(cmd,"lls")) return lls;
    
    if(strstr(cmd,"lcd")!=NULL) return lcd;
    
    if(strstr(cmd,"cd")!=NULL) return cd;
    if(strstr(cmd,"put")!=NULL) return put;
    if(strstr(cmd,"get")!=NULL) return get;
    
    return -1;

}

int handler_cmd(struct Msg msg, int s_fd)
{
	//handle cmd 
	int fd,n_read; 
	char p_pre[12];
	char *p=NULL;
	
	int ret=cmd_to_number(msg.cmd);
    switch(ret){
		case ls:
		case pwd:
		case cd:
			send(s_fd,&msg,sizeof(msg),0);
			break;
		case get:
			send(s_fd,&msg,sizeof(msg),0);
			break;
		case put:
			strcpy(p_pre,msg.cmd);
			printf("dir:%s \r\n",p_pre);
			p=strtok(p_pre," ");
			p=strtok(NULL," ");   //get file_name	
			printf("dir:%s \r\n",p);
			if(!access(p,F_OK)){  //if have this file
				fd=open(p,O_RDONLY);
				
				n_read=read(fd,&msg.data,1024);
				if(n_read>=1024){
					printf("file over 1024! faild! \r\n");
					
				} 

				send(s_fd,&msg,sizeof(msg),0);
				
				memset(&msg.data,0,1024);
				printf("client put cmd is: %s \r\n",msg.cmd);
				
				close(fd);
			}else{   //if no this file
				send(s_fd,"no this file",16,0);
			}
			break;			
		case lls:
			system("ls");
			break;
		case lcd:
			strcpy(p_pre,msg.cmd);
			p=strtok(p_pre," ");
			p=strtok(NULL," ");   //get file_
			printf("dir:%s \r\n",p);
			chdir(p);
			break;
		case quit:
			send(s_fd,&msg,sizeof(msg),0);
			close(s_fd); 
			exit(-1);
	}
	return ret;
}  

void handle_server_msg(struct Msg msg,int s_fd)
{
	int n_read,fd;
	char *p;
	struct Msg recv_msg; //this is new msg   use it becase need pre msg cmd
	
	n_read=read(s_fd,&recv_msg,sizeof(recv_msg));  //while block
	
	if(n_read==0){
		printf("\r\n server is outline! ");
		exit(-1);
	}
	if(recv_msg.flag == dofile){
		p=strtok(msg.cmd," ");
		p=strtok(NULL," ");   //get file_name	
		fd=open(p,O_RDWR|O_CREAT,0666);
		printf("creat the file\r\n");
		write(fd,&recv_msg.data,strlen(recv_msg.data));
		close(fd);
		putchar('>');
		fflush(stdout);
	}else{           //normal direct cmd
		printf("-------------------->\r\n");
		printf("%s >",recv_msg.data);
		printf("--------------------");
		
		putchar('>');
		fflush(stdout);
	}
	
}

int main(int argc,char *argv[])
{
	int flag,s_fd,n_read,ret;
	struct sockaddr_in c_ddr;
	struct Msg msg;
	//1.build socket
	s_fd=socket(AF_INET,SOCK_STREAM,0);
	
	//2.0 prepare server addr
	memset(&c_ddr,0,sizeof(c_ddr)); //clear c_ddr
	c_ddr.sin_family=AF_INET;
	c_ddr.sin_port=htons(8880);
	inet_aton("127.0.0.1",&c_ddr.sin_addr);
	
	//2.connect server get s_fd
			
	if(connect(s_fd,(struct sockaddr *)&c_ddr,sizeof(c_ddr))==-1){
		perror("error");
		exit(-1);
	}
	printf("connect success==============\r\n");
	while(1){
        
		//1.get cmd form keyborad    and  handle cmd to server
		memset(&msg,0,sizeof(msg));
		printf("\r\n >");
		gets(msg.cmd);
		int ret=handler_cmd(msg,s_fd);
		
		
		//2.handle the msg form server
		if(ret==-1){
			printf("no this cmd!\r\n ");
			fflush(stdout);
			continue;
		}
		if(ret==5 || ret==6){
			printf("client cmd!\r\n ");
			fflush(stdout);
			continue;
		}	
		handle_server_msg(msg,s_fd);
		
	}
	close(s_fd);
	return 0;
} 

4.问题总结

  • 在put 发送文件中,当文件大小超过给定字节就会溢出,导致整个结构体崩坏,破坏cmd。
    思考:除了加大给定字节大小,还有其它办法吗?strcpy是怎么实现的
    read函数陷阱:read函数读的字节小于fd文件字节,会崩坏buf里的数据。
  • strtok函数会破坏使用的字符串,要保留原来字符串需要strcpy复制出来处理。
  • 本地命令不用服务器处理的命令,ret=5,ret=6不要进入hanle_server_msg用recv函数阻塞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/969698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习——线性回归/岭回归/Lasso回归

0、前言&#xff1a; 线性回归会用到python第三方库&#xff1a;sklearn.linear_model中的LinearRegression导入第三方库的方法&#xff1a;from sklearn.linear_model import LinearRegression使用LinearRegression(二维数据&#xff0c;一维数据)进行预测&#xff0c;其中数…

YOLOv5,v8中文标签显示问题

本人使用的是YOLOv5-7.0&#xff0c;YOLOv8的最新版本 1. 训练YOLOv5时matplotlib无法显示中文标签 数据集中的标签是中文&#xff0c;在训练YOLOv5&#xff0c;v8算法时&#xff0c;matplotlib库无法显示中文 2 解决方法 在yolov5/utils/plots.py文件中手动添加黑体字体&a…

flutter Could not get unknown property ‘ndkVersion’

使用的 flutter 版本为 3.7.2 &#xff0c;编译运行 如下 Could not get unknown property ‘ndkVersion’ for object of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension 解决方法是 在flutter-3.7.2\packages\flutter_tools\gradle\flutter.gradle配置…

Java特性之设计模式【抽象工厂模式】

一、抽象工厂模式 概述 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式 在抽象工厂模式中&#xff0c;接口是…

2001-2021年上市公司数字化转型(年报词频统计)

2001-2021年上市公司数字化转型&#xff08;年报词频统计&#xff09; 1、时间&#xff1a;2001-2021年 2、来源&#xff1a;上市公司年报、巨潮资讯网 3、方法说明&#xff1a;参考管理世界中吴非&#xff08;2021&#xff09;的做法&#xff0c;对人工智能技术、大数据技术…

警告:Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30

1. 警告 SpringBoot 的 validation 依赖包含有易受攻击的依赖 snakeyaml。 警告信息如下&#xff1a; Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.30 意思是&#xff1a;提供了可传递的易受攻击依赖 maven:org.yaml:snakeyaml:1.30 2. 警告示例 …

networkX-03-连通度、全局网络效率、局部网络效率、聚类系数计算

文章目录 1.连通度1.1 检查图是否连通1.2 检查有向图是否为强连通1.3 点连通度、边连通度&#xff1a; 2.网络效率2.1全局效率2.2 局部效率2.2.1 查找子图2.2.3 局部效率源码分析 3.聚类系数&#xff08;Clustering Coefficient&#xff09;3.1 聚类系统源码分析 教程仓库地址&…

【开学作业考试层出不穷】Python自动答题脚本,在线答题,零基础可学!!(附源码)

前言 大家好 我是小曼呐~ 9月份想必大部分同学已经开学啦&#xff0c;开学少不了老师会布置一些 软件上面的作业 今天教大家用python制作自动答题脚本&#xff0c;100%准确率哦~ 喜欢的同学记得关注 收藏哦~ 环境使用 Python 3.8Pycharm 模块使用 import requests —>…

MySQL表的内连和外连

文章目录 MySQL表的内连和外连1. 内连接(1) 显示SMITH的名字和部门名称 2. 外连接2.1 左外连接(1) 查询所有学生的成绩&#xff0c;如果这个学生没有成绩&#xff0c;也要将学生的个人信息显示出来 2.2 右外连接(1) 对stu表和exam表联合查询&#xff0c;把所有的成绩都显示出来…

【Apollo学习笔记】——规划模块TASK之SPEED_BOUNDS_PRIORI_DECIDERSPEED_BOUNDS_FINAL_DECIDER

文章目录 前言SPEED_BOUNDS_PRIORI_DECIDER功能简介SPEED_BOUNDS_FINAL_DECIDER功能简介SPEED_BOUNDS_PRIORI_DECIDER相关配置SPEED_BOUNDS_FINAL_DECIDER相关配置SPEED_BOUNDS_DECIDER流程将障碍物映射到ST图中ComputeSTBoundary(PathDecision* path_decision)ComputeSTBounda…

MybatisPlus 快速入门 常见注解 配置

var code "81563903-534d-4850-9d6a-a9fb0318f593" 本课程全面讲解了Mybatis框架的使用&#xff0c;从快速入门到原理分析再到实战应用。每一个知识点都有案例进行演示学习&#xff0c;最终通过学习你将全面掌握&#xff0c;从而使Mybatis的开发更加的高效&#xff…

网络编程 day 6

1、基于UDP聊天室 服务器 #define ERR_MSG(msg) do{\fprintf(stderr,"__%d__",__LINE__);\perror(msg);\ }while(0) #define IP "127.0.0.1" #define PORT 6666 //创建链表 Linklistptr list_create(); Linklistptr node_buy(datatype e); int list_insert…

You must install at least one postgresql-client-<version> package

使用主机上的映射端口来连接到 PostgreSQL 数据库。例如&#xff0c;使用以下命令连接到数据库&#xff1a; psql -h localhost -p 5432 -U postgres出现下面的问题&#xff1a; 分析&#xff1a; 如果您在运行 psql 命令时遇到错误消息 You must install at least one pos…

flex布局轻而易举实现页面布局;超详细解析轻松掌握

我们曾如此渴望命运的波澜&#xff0c;到最后才发现&#xff0c;人生最曼妙的风景&#xff0c;竟是内心的淡定和从容。我们曾如此期盼外界的认可&#xff0c;到最后才知道&#xff0c;世界是自己的&#xff0c;与他人毫无关系。——杨绛 开始 痛点 网页布局&#xff08;layout…

数据分析因子评分学习

当多个因素影响一个结果时&#xff0c;我们需要综合考虑这些因素分别对结果德影响。因子评分就是用于比较其对结果德影响程度。 文章目录 前言一、案例背景二、解决方案&#xff08;一&#xff09;分析思路&#xff08;二&#xff09;剔除无关数据&#xff08;三&#xff09;求…

role、user、schema在Oracle、MySQL、PostgreSQL的区别

0.先上结论 数据库逻辑可以细分为&#xff1a;角色、用户、数据库、模式PostgreSQL和MySQL合并了角色和用户&#xff0c;MySQL还合并了数据库、模式Oracle合并了用户、数据库、模式 1.图 1.1.架构 1.2.用户和角色 1.2.1.PostgreSQL 1.2.2.MySQL 1.2.3.Oracle 参考文章 数据…

安卓绘制原理概览

绘制原理 Android 程序员都知道 Android 的绘制流程分为 Measure、Layout、Draw 三步骤&#xff0c;其中 Measure 负责测量 View 的大小Layout 负责确定 View 的位置Draw 负责将 View 画在屏幕上 由 ViewRootImpl 实现的 performTraversal 方法是 Measure、layout、draw 的真正…

教育培训小程序的设计与功能解析

随着互联网的发展&#xff0c;线上教育逐渐成为一种趋势&#xff0c;越来越多的人开始选择在线学习。而搭建一个适合自己的线上教育小程序&#xff0c;可以为教育机构或个人提供更好的教学和学习体验。在本文中&#xff0c;我们将介绍如何通过一个第三方制作平台来搭建在线教育…

【Maven教程】(五)仓库:解析Maven仓库—布局、分类和配置,远程仓库的认证与部署,快照版本,依赖解析机制,镜像和搜索服务 ~

Maven 仓库 1️⃣ 什么是Maven仓库2️⃣ 仓库的布局3️⃣ 仓库的分类3.1 本地仓库3.2 远程仓库3.3 中央仓库3.4 私服 4️⃣ 远程仓库的配置4.1 远程仓库的认证4.2 部署至远程仓库 5️⃣ 快照版本6️⃣ 从仓库解析依赖的机制7️⃣ 镜像8️⃣ 仓库搜索服务8.1 Sonatype Nexus8.2…

大白菜清理电脑密码教程

首先安装大白菜&#xff1a; 插入u盘一键制作启动盘 制作成功&#xff0c;重启进入u盘启动模式