Linux应用编程,网络编程练习--------ftp云盘(详细版)

本文详述了一次Linux编程的学习经历,通过socket实现服务端与客户端的连接,包括客户端的文件操作(ls, cd, lls, lcd, get, put)及服务端的指令接收与执行。文章介绍了实现思路、具体流程,涉及socket连接、指令定义、信息交互等关键步骤,展示了完整的代码实现,并进行了反思与总结。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本文章是前段时间学习linux编程的一个小总结,如果不总结的话我怕我学完就忘emmm(其实已经忘的差不多了),本文是跟着上官可编程老师与朱有鹏老师学习之后的练手作品,本人学疏才浅,暂时只能到这个地步


提示:以下是本篇文章正文内容

一、实现的功能

利用socket,建立起服务端与客户端的对接;(服务端能支持多台客户端的同时连接)

1.客户端

1、客户端输入ls指令,能获取服务端上文件列表。
2、客户端输入cd指令+路径,可以切换服务端的目录。
3、在程序运行的过程中,客户端输入lls指令 能够查看自己的文件列表
4、在程序运行的过程中,客户端输入lcd指令+路径 能够切换自己的目录。
5、客户端输入get指令+文件名,能将服务端上面的某个文件下载到客户端
6、客户端输入put指令+文件名,能将客户端上面的某个文件上传到服务端

2.服务端

1、不断监听客户端的指令(等待指令)。
2、在接收上面客户端的指令后,去执行指令。


二、实现思路

1.建立socket连接

(1)服务端建立socket连接:socket—>blind—>listen—>accept
(2)客户端建立socket连接:socket—>connect

2.客户端和服务端进行信息的交互

(1)定义指令
(2)客户端匹配用户输入的指令,客户端发送指令到服务端,服务端解析指令作出响应


三、具体流程分析(代码)

第一步:建立socket连接

服务端建立socket连接
流程:socket—>blind—>listen—>accept
代码如下(示例):

int main(int argc,char **argv)
{
   
   
        int c_fd;
        int s_fd;
        int n_read;
        char readBuf[128];

        struct Msg msg;
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;
        
/*调试信息,这里我想要用argv,argc,进行手动指定端口号和IP地址,所以在用这两个参数之前需要先判断*/
        if(argc != 3){
   
   
                printf("parameter error!\n");
                exit(-1);
        }
        
/*用之前清空,防止数据产生混乱*/
        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket
        /*s_fd:这里socket返回的是监听fd,是用来监听客户端的,不能用来和任何客户端进行读写*/
        /*AF_INET:IPv4,SOCK_STREAM:tcp协议,0:使用系统默认的方式*/
        s_fd = socket(AF_INET,SOCK_STREAM,0);
        /*如果返回值为-1说明错误,打印出错误号*/
        if(s_fd == -1){
   
   
                perror("socket");
                exit(-1);
        }
        
        //2.bind
        /*有IPv4和IPv6两种,这里我们选IPv4*/
        s_addr.sin_family = AF_INET;   // 设置地址族为IPv4
        /*htons:端口号大小端的转换(具体大小端要看对应的计算机)
		atoi:字符串转换成整型,使我们输入的数字端口号可以被识别
		*/
        s_addr.sin_port = htons(atoi(argv[2]));  // 设置地址的端口号信息
        /*inet_aton:将我们输入的地址字符串转换成网络可以识别的api*/
        inet_aton(argv[1],&s_addr.sin_addr);  // 设置IP地址
        /*(struct sockaddr *)&s_addr这之所以需要类型转换的原因是因为我们用的是IPV4的结构体,而给出的标准是IPV4和IPV6的通用结构体,所以我们一般用IPV4的结构体之后将其转换为系统给出的通用结构体,其实转不转都一样,就是会报警告而已,而这个警告是我们可以理解的警告,所以问题不大*/
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        //3.listen
        /*设置最大监听10个*/
        listen(s_fd,10);
        
        //4.accept
        int clen = sizeof(struct sockaddr_in);
	/*while不停的循环接收客户端发来的信息,并且作出响应*/
        while(1){
   
   
        /*accept返回的fd叫做连接fd,用来和连接那端的客户端程序进行读写。*/
                c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
                /*调试信息*/
                if(c_fd != -1){
   
   
                        perror("accept");
                }
/*成功打印出连接的地址*/
                printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));
/*当我的accept每接收到一个信息就建立一个子进程*/
                if(fork() == 0){
   
   

                        while(1){
   
   
                        /*每次循环接收信息之前,清空之前的信息*/
                                memset(msg.cmd,0,sizeof(msg.cmd));
                                /*用accept建立的连接fd来读写信息*/
                                n_read = read(c_fd,&msg,sizeof(msg));
                                if(n_read == 0){
   
   
                                        printf("client out\n");
                                        break;
                                }else if(n_read > 0){
   
   
                                /*一旦发现有信息,就执行这个函数*/
                                        msg_handler(msg,c_fd);
                                }
                        }
           }
        }
/*关闭监听fd和连接fd*/
        close(c_fd);
        close(s_fd);
        return 0;
}

客户端建立socket连接
流程:socket—>connect
客户端建立socket与服务端建立socket大同小异这里就不过多赘述了
代码如下(示例):

int main(int argc,char **argv)
{
   
   
        int c_fd;
        struct Msg msg;
        struct sockaddr_in c_addr;

        if(argc != 3){
   
   
                printf("parameter error!\n");
                exit(-1);
        }

        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket
        c_fd = socket(AF_INET,SOCK_STREAM,0);
        if(c_fd == -1){
   
   
                perror("socket");
                exit(-1);
        }
        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&c_addr.sin_addr);

        //2.connect
        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
   
   
                perror("connect");
                exit(-1);
        }
        printf("connect ...\n");
        return 0;

}

第二步:客户端和服务端进行信息的交互

定义指令
共有指令
代码如下(示例):


#define LS   0
#define PWD  1
#define GET  2

#define IFGO 3

#define CD   4
#define PUT  5
#define LLS  6
#define LCD  7
#define LPWD 8

#define QUIT 9
#define DOFILE 10

struct Msg
{
   
   
        int type;
        char cmd[1024];
        char buf[128];

};

服务端指令
代码如下(示例):

int get_cmd_type(char *cmd)  //检测命令并转为相应int
{
   
   
        if(!strcmp("ls",cmd))           
Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程TCP/IP基础篇 Linux网络编程之socket编程Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输单元(MTU)/路径MTU 以太网帧格式 ICMP ARP RARP 03TCPIP基础(三) IP数据报格式 网际校验和 路由 04TCPIP基础(四) TCP特点 TCP报文格式 连接建立三次握手 连接终止四次握手 TCP如何保证可靠性 05TCPIP基础(五) 滑动窗口协议 UDP特点 UDP报文格式 Linux网络编程之socket编程篇 06socket编程(一) 什么是socket IPv4套接口地址结构 网络字节序 字节序转换函数 地址转换函数 套接字类型 07socket编程(二) TCP客户/服务器模型 回射客户/服务器 socket、bind、listen、accept、connect 08socket编程(三) SO_REUSEADDR 处理多客户连接(process-per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与SIGCHLD信号 12socket编程(七) TCP 11种状态 连接建立三次握手、连接终止四次握手 TIME_WAIT与SO_REUSEADDR SIGPIPE 13socket编程(八) 五种I/O模型 select 用select改进回射客户端程序 14socket编程(九) select 读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write_timeout函数封装 accept_timeout函数封装 connect_timeout函数封装 17socket编程(十二) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程之进程间通信篇 23进程间通信介绍(一) 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对象的持续性 24进程间通信介绍(二) 死锁 信号量 PV原语 用PV原语解决司机与售票员问题 用PV原语解决民航售票问题 用PV原语解决汽车租赁问题 25System V消息队列(一) 消息队列 IPC对象数据结构 消息队列结构 消息队列在内核中的表示 消息队列函数 26System V消息队列(二) msgsnd函数 msgrcv函数 27System V消息队列(三) 消息队列实现回射客户/服务器 28共享内存介绍 共享内存 共享内存示意图 管道、消息队列与共享内存传递数据对比 mmap函数 munmap函数 msync函数 29System V共享内存 共享内存数据结构 共享内存函数 共享内存示例 30System V信号量(一) 信号量 信号量集结构 信号量集函数 信号量示例 31System V信号量(二) 用信号量实现进程互斥示例 32System V信号量(三) 用信号集解决哲学家就餐问题 33System V共享内存与信号量综合 用信号量解决生产者消费者问题 实现shmfifo 34POSIX消息队列 POSIX消息队列相关函数 POSIX消息队列示例 35PO
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值