TCP实现FTP功能

这篇具有很好参考价值的文章主要介绍了TCP实现FTP功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

server

client

makefile

 运行顺序


FTP(File Transfer Protocol)是一种用于在计算机网络上传输文件的标准协议。

它允许用户通过网络将文件从一个计算机(称为FTP服务器)传输到另一个计算机(称为FTP客户端)

以下是FTP的一般工作流程:

  1. 建立连接:客户端使用FTP客户端软件连接到FTP服务器;
  2. 身份验证:客户端在连接建立后,提供登录凭据;
  3. 导航文件系统:验证成功,客户端可以浏览FTP服务器上的文件系统,并选择要上传或下载的文件;
  4. 上传文件:客户端可以选择要上传到FTP服务器的本地文件,并将其发送到服务器;
  5. 下载文件:客户端可以选择要从FTP服务器下载的文件,并将其复制到本地计算机;
  6. 其他操作:FTP还支持其他操作,例如重命名文件、删除文件、创建文件夹等;
项目功能介绍:
均有服务器和客户端代码,基于TCP写的。
在同一路径下,将客户端可执行代码复制到其他的路径下,接下来再不同的路径下运行服务器和客户端。
相当于另外一台电脑在访问服务器。
客户端和服务器链接成功后出现以下提示:四个功能
***************list************** //列出服务器所在目录下的文件名(除目录不显示)
***********put filename********** //上传一个文件
***********get filename********** //重服务器所在路径下载文件
**************quit*************** //退出(可只退出客户端,服务器等待下一个客户端链接)

server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void list_server(int acceptfd, char *buf, int size);	//list功能
void put_server(int acceptfd, char *buf, int size);		//put功能
void get_server(int acceptfd,char *buf, int size);		//get功能
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("please input %s <port>\n", argv[0]);
        return -1;
    }
    //1.创建流式套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //链接
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    printf("sockfd:%d\n", sockfd); //3
    //填充ipv4的通信结构体

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1])); //"8888" int a= atoi("8888")//a=8888
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    socklen_t len = sizeof(caddr);

    //2.绑定套接字 ip和端口(自己)
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err.");
        return -1;
    }
    printf("bind ok.\n");

    //3.监听
    if (listen(sockfd, 5) < 0)
    {
        perror("listen err.");
        return -1;
    }
    printf("listen ok.\n");
    //4.阻塞等待客户端链接
    while (1)
    {
        int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err.");
            return -1;
        }
        printf("acceptfd=%d\n", acceptfd); //通信
        printf("client:ip=%s port=%d\n",
               inet_ntoa(caddr.sin_addr),
			   ntohs(caddr.sin_port));
        //循环收发消息
        char buf[128];
        int ret;
        while (1)
        {
            ret = recv(acceptfd, buf, sizeof(buf), 0);
            if (ret < 0)
            {
                perror("recv err.");
                return -1;
            }
            else if (ret == 0)
            {
                printf("client exit\n");
                break;
            }
            else
            {
                if (strncmp(buf, "list", 4) == 0)
                { //打开当前目录读文件判断文件是普通文件将文件名传给客户端
                    list_server(acceptfd, buf, sizeof(buf));
                }
                else if (strncmp(buf, "put ", 4) == 0)
                { //接收文件(本地:打开新建文件接收客户端发送过来的内容写到文件)
                    put_server(acceptfd, buf, sizeof(buf));
                }
                else if (strncmp(buf, "get ", 4) == 0)
                { //发送文件
                    //(本地:打开文件读文件内容发送给客户端)
                    get_server(acceptfd, buf, sizeof(buf));
                }
            }
        }
        close(acceptfd);
    }
    close(sockfd);
    return 0;
}

//3、get
void get_server(int acceptfd,char *buf, int size) //buf->put xxx.c
{
    //1>打开文件 读
    int fd = open(buf + 4, O_RDONLY);	//buf->put xxx.c
    if (fd < 0)
    {
        perror("open file err.");
        return;
    }
    int ret; //实际读到的个数
    while ((ret = read(fd, buf, size - 1)) != 0)
    {
        buf[ret] = '\0';				// 将读取的内容以字符串形式结束
        send(acceptfd, buf, size, 0);	// 发送读取的内容给客户端
    }
    strcpy(buf, "get ok.");				// 将"get ok."字符串复制到缓冲区
    send(acceptfd, buf, size, 0);		// 发送"get ok."给客户端
}
//2.接收文件(本地:打开新建文件接收客户端发送过来的内容写到文件)
void put_server(int acceptfd, char *buf, int size)
{
	 // 1. 打开文件,以写入方式打开(如果不存在则创建,如果存在则清空内容)
    int fd = open(buf + 4, O_TRUNC | O_CREAT | O_WRONLY, 0666);
    if (fd < 0)
    {
        perror("open err.");
        return;
    }
    while (1)
    {
		// 2. 接收客户端发送的数据
        if (recv(acceptfd, buf, size, 0) < 0)
        {
            perror("recv err.");
            return;
        }
		// 3. 检查是否接收到结束标识"put ok."
        if (strncmp(buf, "put ok.", 7) == 0)
            break;
		// 4. 将接收到的数据写入文件
        write(fd, buf, strlen(buf));
    }
}

//list:打开当前目录读文件判断文件是普通文件将文件名传给客户端
void list_server(int acceptfd, char *buf, int size)
{
    //1.打开当前目录文件
    DIR *dir = opendir("./");
    if (dir == NULL)
    {
        perror("opendir err.");
        return;
    }
    //2.循环读目录文件  readdir
    struct dirent *dp = NULL;
    struct stat st;
    while ((dp = readdir(dir)) != NULL)
    {
        //dp->d_name拿到的文件名
        //判断文件属性stat
        stat(dp->d_name, &st);
        if (S_ISREG(st.st_mode))
        {
            strcpy(buf, dp->d_name);		// 将文件名拷贝到缓冲区		
            send(acceptfd, buf, size, 0);	// 发送文件名给客户端
        }
    }
    //发送结束标志
    strcpy(buf, "list ok.");
    send(acceptfd, buf, size, 0);
}

client

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void show(void);
void list_client(int sockfd, char *buf, int size);
void put_client(int sockfd, char *buf, int size);
void get_client(int sockfd, char *buf, int size);
int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("please input %s <ip> <port>\n", argv[0]);
        return -1;
    }
    //1.创建套接子
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    //填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));
    saddr.sin_addr.s_addr = inet_addr(argv[1]);
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err.");
        return -1;
    }
    //收发消息
    char buf[128];
    while (1)
    {
        //1.请求窗口
        show();
        //2.获取请求
        fgets(buf, sizeof(buf), stdin);
        if (buf[strlen(buf) - 1] == '\n')
            buf[strlen(buf) - 1] = '\0';
		
        send(sockfd, buf, sizeof(buf), 0);
		
        if (strncmp(buf, "list", 4) == 0)
        { 	//循环接收服务器发送过来的普通文件名输出到终端
            list_client(sockfd, buf, sizeof(buf));
        }
        else if (strncmp(buf, "put ", 4) == 0)
        { 	//上传文件(本地:打开文件读内容发送给服务器)
            put_client(sockfd,buf,sizeof(buf));
        }
        else if (strncmp(buf, "get ", 4) == 0)
        { 	//下载服务器路径下的文件
        	//(本地:打开新建文件接收服务器发送过来的内容写到文件)
            get_client(sockfd,buf,sizeof(buf));
        }
        else if (strncmp(buf, "quit", 4) == 0)
        {
            break;
        }
    }
    close(sockfd);
    return 0;
}
//3.get
void get_client(int sockfd, char *buf, int size)
{
    int fd = open(buf + 4, O_TRUNC | O_CREAT | O_WRONLY, 0666);
    if (fd < 0)
    {
        perror("open err.");
        return;
    }
    while (1)
    {
        if (recv(sockfd, buf, size, 0) < 0)
        {
            perror("recv err.");
            return;
        }
        if (strncmp(buf, "get ok.", 7) == 0)
            break;
        write(fd, buf, strlen(buf));
    }
}
//2.put 上传文件(本地:打开文件读内容发送给服务器)
void put_client(int sockfd, char *buf, int size) //buf->put xxx.c
{
    //1>打开文件 读
    int fd = open(buf + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open file err.");
        return;
    }
    int ret; //实际读到的个数
    while ((ret = read(fd, buf, size - 1)) != 0)
    {
        buf[ret] = '\0';
        send(sockfd, buf, size, 0);
    }
    strcpy(buf, "put ok.");
    send(sockfd, buf, size, 0);
}

//1.list:循环接收服务器发送过来的普通文件名输出到终端
void list_client(int sockfd, char *buf, int size)
{

    while (1)
    {
        if (recv(sockfd, buf, size, 0) < 0)
        {
            perror("list recv err.");
            return;
        }
        if (strncmp(buf, "list ok.", 8) == 0)
        {
            break;
        }
        printf("%s\n", buf);
    }
}

void show(void)
{
    printf("************list***************\n");
    printf("************put filename*******\n");
    printf("************get filename*******\n");
    printf("************quit***************\n");
}

makefile

all:
	gcc server.c -o ser		
	gcc client.c -o cli	
.PHONY:clean	
clean:
	rm ser cli	

 运行顺序

TCP实现FTP功能,网络编程,tcp/ip,网络协议,网络文章来源地址https://www.toymoban.com/news/detail-600126.html

到了这里,关于TCP实现FTP功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络编程day2——基于TCP/IP协议的网络通信

            计算机S                                                 计算机C      创建socket对象                                   创建socket对象      准备通信地址(自己的ip(非公网ip))      准备通信地址                                     (计算

    2024年02月10日
    浏览(51)
  • 网络编程1—— IP地址 + 端口号 +TCP/IP协议 + 协议分层的封装与应用

    本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下! 从本篇文章开始就要分享网络编程的内容了,越发的感受到了编程的魅力,鸡汤来喽!! 1️⃣单机阶段:计算机跟计算

    2024年02月12日
    浏览(31)
  • 【Java网络编程】OSI七层网络模型与TCP/IP协议簇

    1.1、OSI七层网络模型 OSI七层网络模型中,每层的功能如下: 应用层:人与计算机网络交互的窗口。 表示层:负责数据格式的封装,如加密、压缩、编解码等。 会话层:建立、终止、管理不同端间的会话连接。 传输层:提供端到端(两台机器)之间的传输机制,以及提供流

    2024年04月11日
    浏览(36)
  • 【Java EE初阶十五】网络编程TCP/IP协议(二)

            tcp的socket api和U大片的socket api差异很大,但是和前面所讲的文件操作很密切的联系         下面主要讲解两个关键的类:         1、ServerSocket:给服务器使用的类,使用这个类来绑定端口号         2、Socket:即会给服务器使用,又会给客户端使用;         

    2024年02月20日
    浏览(40)
  • Java网络编程之IP,端口号,通信协议(UDP,TCP)

    ① C/S :客户端/服务器 在用户本地需要下载安装客户端程序,在远程有一个服务器端程序。 优点:画面精美,用户体验好 缺点:用户需要下载更新 ② B/S :浏览器/服务器 只需要一个浏览器,用户通过指定网址访问对应的服务器。 优点:不需要开发客户端,只需要页面+服务

    2024年02月03日
    浏览(49)
  • TCP/IP网络编程(二) 套接字协议及其数据传输特性

    关于协议 如果相隔比较远的两人进行通话,必须先决定通话方式,如果一方选择电话,另一方也必须选择电话,否则接受不到消息。 总之,协议就是为了完成数据交换而定好的约定。 创建套接字 协议族 通过socket函数的第一个参数传递套接字中使用的协议分类信息,此协议

    2024年02月10日
    浏览(43)
  • 【Qt网络编程】实现TCP协议通信

    传输控制协议(TCP,Transmission Control Protocol)是 一种面向连接的、可靠的、基于字节流的传输层通信协议 ,由IETF的RFC 793 定义。 TCP建立连接前,需要进行三次握手,如下图所示: TCP断开连接前,需要进行四次挥手,如下图所示: Qt中提供了QTcpSocket类和QTcpServer类分别用于创

    2024年02月16日
    浏览(39)
  • 《TCP/IP网络编程》--基于TCP实现字符串对话和文件传输

    主要需求:         服务器端和客户端各传递 1 次字符串,基于 TCP 协议,传递字符串前先以 4 字节整数型方式传递字符串长度,剩余部分为字符串数据; 注:下面的代码基于 Windows 系统实现; 项目链接:Chapter5

    2024年02月09日
    浏览(38)
  • TCP/IP网络编程(1)——基于TCP的服务端和客户端的简单实现

    目录 前言 一、服务器端函数 1. 创建套接字函数 socket 2. 套接字绑定地址函数 bind 3. 等待连接请求函数 listen 4. 处理连接请求函数 accept 5. 关闭套接字函数 close 二、客户端函数 1. 请求连接函数 connect 三、完整代码 四、 基于TCP的半关闭 shutdown 五、 套接字可选项 getsockopt setsoc

    2024年02月07日
    浏览(42)
  • Linux网络编程——C++实现进程间TCP/IP通信

    地址接口 1、通用地址接口 共16字节 = 2字节地址类型 + 14字节地址数据 2、自定义地址接口 地址转换 1、需要将点分字符串ip转化为程序ip,使用inet_addr函数: 2、字节序转换 地址接口配置中的端口需要字节序转换,网络规定使用大端字节序。 地址接口配置 1、socket:创建套接

    2024年02月20日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包