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

目录

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_namelcd 对客户端目录的操作 +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 numberif(!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 backchdir(p);break;case get:p=strtok(cmd," ");p=strtok(NULL," ");printf("dir:%s \r\n",p);	if(!access(p,F_OK)){  //if have this filemsg.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 filesend(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 backbreak;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 msgstruct sockaddr_in c_ddr;  //save clinet msgs_fd= socket(AF_INET, SOCK_STREAM, 0);//1.build a soket specifiedif(s_fd==-1){perror("error is");}//2.build all binds_ddr.sin_family=AF_INET;s_ddr.sin_port=htons(8880);s_ddr.sin_addr.s_addr=htonl(INADDR_ANY);//give the bindbind(s_fd,(struct sockaddr *)&s_ddr,sizeof(s_ddr));//3.waite for clientlisten(s_fd,8);//4.accept come and connect for oncelen=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_fdif(fork()==0){   //creat kid pid for handler msg and cmd //5.2 read	while(1){memset(&msg,'\0',sizeof(msg));   //clear msgprintf("====================\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 filefd=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 filesend(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 cmdn_read=read(s_fd,&recv_msg,sizeof(recv_msg));  //while blockif(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 cmdprintf("-------------------->\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 sockets_fd=socket(AF_INET,SOCK_STREAM,0);//2.0 prepare server addrmemset(&c_ddr,0,sizeof(c_ddr)); //clear c_ddrc_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_fdif(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 servermemset(&msg,0,sizeof(msg));printf("\r\n >");gets(msg.cmd);int ret=handler_cmd(msg,s_fd);//2.handle the msg form serverif(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.rhkb.cn/news/125187.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker搭建个人网盘和私有仓库Harbor

目录 1、使用mysql:5.7和 owncloud 镜像&#xff0c;构建一个个人网盘 2、安装搭建私有仓库 Harbor 1、使用mysql:5.7和owncloud&#xff0c;构建一个个人网盘 1.拉取mysql:5.6镜像&#xff0c;并且运行mysql容器 [rootnode8 ~]# docker pull mysql:5.7 [rootnode8 ~]# doc…

8.Redis-set

Set 常用命令saddsmemberssismemberscardspopsmovesrem集合间操作sinter 交集sinterstoresunion 并集sunionstoresdiff 差集sdiffstore 命令总结 内部编码应用场景使用 set来保存用户的“标签” set(集合)就是把一些有关联的数据放刀一起。 它与list的区别如下&#xff1a; 集合…

DeU-Net: 用于三维心脏mri视频分割的可变形(Deformable)U-Net

论文链接&#xff1a;https://arxiv.org/abs/2007.06341 代码链接&#xff1a;文章都看完了实在找不到代码&#xff01;好崩溃&#xff01;好崩溃&#xff01;已经发邮件联系作者&#xff01; 摘要 心脏磁共振成像(MRI)的自动分割促进了临床应用中高效、准确的体积测量。然而…

如何在SOLIDWORKS中更改单位-硕迪科技

SOLIDWORKS中的单位系统 SOLIDWORKS中的单位系统可以针对单个文件修改、一次修改多个文件以及在默认模板中进行修改。每个SOLIDWORKS文件都有一个单位系统&#xff0c;该单位系统由该文件的文档属性控制。默认情况下&#xff0c;SOLIDWORKS零件、装配体和工程图模板各自规定了…

【AIGC专题】Stable Diffusion 从入门到企业级应用0414

一、前言 本文是《Stable Diffusion 从入门到企业级应用实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》的第0414篇 利用Stable Diffusion ControlNet 法线贴图模型精准控制图像生成。本部分内容&#xff0c;位于整个Stable Diffusion生态体…

BLE Mesh蓝牙mesh网多跳大数据量高带宽传输数据方法

1、BLE Mesh数据传输现状 BLE Mesh网络技术是低功耗蓝牙的一个进阶版&#xff0c;Mesh扩大了蓝牙在应用中的规模和范围&#xff0c;因为它同时支持超过三万个网络节点&#xff0c;可以跨越大型建筑物&#xff0c;不仅可以使得医疗健康应用更加方便快捷&#xff0c;还能监测像学…

Python调用Jumpserver的Api接口增删改查

引言 Jumpserver是一款强大的堡垒机系统&#xff0c;可以有效管理和控制企业内部服务器的访问权限&#xff0c;提高网络安全性。本文将介绍如何使用Python编程语言&#xff0c;结合Jumpserver提供的API接口&#xff0c;实现对跳板机的管理和操作。 1、什么是Jumpserver&#…

Python Tcp编程

网络连接与通信是我们学习任何编程语言都绕不过的知识点。Python 也不例外&#xff0c;本文就介绍因特网的核心协议 TCP &#xff0c;以及如何用 Python 实现 TCP 的连接与通信。 TCP 协议 TCP协议&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#…

code阶段——gitgitlab安装

在code阶段&#xff0c;我们需要将不同版本的代码存储到一个仓库中&#xff0c;常见的版本控制工具就是SVN或者Git&#xff0c;这里我们采用Git作为版本控制工具&#xff0c;GitLab作为远程仓库。 Git安装 https://git-scm.com/&#xff08;傻瓜式安装&#xff09; GitLab安…

leetcode 143. 重排链表

2023.9.5 先将链表中的节点存储到数组中&#xff0c;再利用双指针重新构造符合条件的链表。代码如下&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNod…

第15章_锁: (表级锁、页级锁、行锁、悲观锁、乐观锁、全局锁、死锁)

3.2 从数据操作的粒度划分&#xff1a;表级锁、页级锁、行锁 为了提高数据库并发度&#xff0c;每次锁定的数据范围越小越好&#xff0c;理论上每次只锁定当前操作的数据的方案会得到最大的并发度&#xff0c;但管理锁是很耗资源&#xff08;涉及获取、检查、释放锁等动作)。因…

统一潮流控制器 (UPFC) 的应用,以增强电力系统中的电压稳定性(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

智能机器人:打造自动化未来的关键技术

文章目录 1. 智能机器人的基本概念2. 智能机器人的关键技术2.1 机器视觉2.2 机器学习与深度学习2.3 传感器技术 3. 智能机器人的应用领域3.1 制造业3.2 医疗保健3.3 农业3.4 服务业 4. 智能机器人的未来趋势4.1 自主决策能力的提升4.2 协作与互操作性4.3 个性化定制4.4 环境感知…

4.矩阵的几何意义、变基与迹

文章目录 变基操作与矩阵矩阵的迹几何意义矩阵迹的几条性质 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 变基操作与矩阵 我们知道空间中一点的坐标可以表示以原点为起点以该点为终点的向量。 以二维平面为例&#xff0c;如下图 选取…

对可再生能源和微电网集成研究的新控制技术和保护算法进行基线和测试及静态、时域和频率分析研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

在VScode中如何将界面语言设置为中文

VSCode安装后的默认界面是只有英文的&#xff0c;如果想用中文界面&#xff0c;那么就需要安装对应的插件&#xff0c;vscode插件可以从扩展中心去搜索并安装。 安装vscode后打开vscode&#xff0c;点击左侧的扩展按钮。 在搜索框中输入chinese&#xff0c;弹出chinese&#x…

1.2 向量代数

1.向量的概念 定义&#xff1a; 既有大小&#xff0c;又有方向。 向量的表示法 记有向线段的起点A与终点B&#xff0c;从点A指向B的箭头表示了这条线端的方向&#xff0c;线段的长度表示了这条线段的大小&#xff0c;向量就可用这样的一条有向线段来表示&#xff0c; 记作&a…

4. xaml Button按钮

1.运行图片 2.源码 <Grid><!--BorderBrush="BlueViolet" 边框颜色--><!--BorderThickness="2" 边框线的粗细--><

ROS2学习(一):Ubuntu 22.04 安装 ROS2(Iron Irwini)

文章目录 一、ROS2(Iron Irwini)介绍二、ROS2(Iron Irwini)安装1.设置编码2.使能代码库3.安装ROS2 Iron 三、ROS2测试四、ROS2卸载 一、ROS2(Iron Irwini)介绍 官方文档 Iron Irwini版本支持的平台如下&#xff1a; 二、ROS2(Iron Irwini)安装 1.设置编码 sudo apt update…

花生壳内网穿透+Windows系统,如何搭建网站?

1. 准备工作 在百度搜索“Win7下安装ApachePHPMySQL”&#xff0c;根据搜到的教程自行安装WAMP环境。 如果在网页上键入http://127.0.0.1/ 出现以下页面表示您的服务器已经建好&#xff0c;下一步就是关键&#xff0c;如何通过花生壳内网穿透&#xff0c;让外网的用户访问到您…