c语言实现FTP

这个实现了客户端和服务端文件的相互传输(只在本机上运行过),如果是要两台计算机相互传数据要改ip

给大家看一下实现过程(.exe文件要先开服务端的)

输入1

直接将快捷方式拖拽上去就有绝对路径了,然后回车

用的是分组传输

然后服务端就接受到传输的文件了 ,从服务端取文件的过程是一样的。

上代码

客户端的头文件

ftpclient.h

#pragma once
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")  // 加载静态库
#include <stdbool.h>
 
#define SPORT 8888                 // 服务器端口号
#define PACKET_SIZE (1024 - sizeof(int) * 3)
 
 
 
// 定义标记
enum MSGTAG
{
    MSG_FILENAME = 1,        // 文件名称                服务器使用
    MSG_FILESIZE = 2,        // 文件大小                客户端使用
    MSG_READY_READ = 3,        // 准备接受                客户端使用
    MSG_SENDFILE = 4,        // 发送                    服务器使用
    MSG_SUCCESSED = 5,        // 传输完成                两者都使用
    MSG_OPENFILE_FAILD = 6,         // 告诉客户端文件找不到    客户端使用
    MSG_CLIENTREADSENT = 7,        //客户端发送路径和文件大小
    MSG_SERVERREAD  = 8,        //服务端申请空间
    MSG_CLIENTSENT = 9            //客户端传输
 
};
 
#pragma pack(1)                     // 设置结构体1字节对齐**************
 
struct MsgHeader                    // 封装消息头
{
    enum MSGTAG msgID;              // 当前消息标记   4
    union MyUnion
    {
        struct Mystruct
        {
            int fileSize;           // 文件大小  4
            char fileName[256];     // 文件名    256
        }fileInfo;
        struct
        {
            int nStart;             // 包的编号
            int nsize;              // 该包的数据大小
            char buf[PACKET_SIZE];
        }packet;
    };
 
};
 
#pragma pack()
 
// 初始化socket库
bool initSocket();
 
// 关闭socket库
bool closeSocket();
 
// 监听客户端连接
void connectToHost();
 
// 处理消息
bool processMag(SOCKET serfd);
 
// 获取文件名
void downloadFileName(SOCKET serfd);
 
// 文件内容读进内存
void readyread(SOCKET, struct MsgHeader*);
 
// 写入文件内容
bool writeFile(SOCKET, struct MsgHeader*);
 
//服务端发送文件路径和大小 然后在自己的缓冲区将文件缓存下来
void clientReadySend(SOCKET);
 
//准备开始发送文件
bool sendFile(SOCKET, struct MsgHeader*);


客户端.c文件 

ftpclient.c

#include <stdio.h>
#include <stdlib.h>       
#include "ftpclient.h"   
 
char g_fileName[256];     // 保存服务器发送过来的文件名
char* g_fileBuf;          // 接受存储文件内容
char g_recvBuf[1024];     // 接受消息缓冲区
int g_fileSize;           // 文件总大小
 
int main(void)
{
    initSocket();
 
    connectToHost();
 
    closeSocket();
 
    return 0;
}
 
// 初始化socket库
bool initSocket()
{
    WSADATA wsadata;
 
    if (0 != WSAStartup(MAKEWORD(2, 2), &wsadata))        // 启动协议,成功返回0
    {
        printf("WSAStartup faild: %d\n", WSAGetLastError());
        return false;
    }
 
    return true;
}
 
// 关闭socket库
bool closeSocket()
{
    if (0 != WSACleanup())
    {
        printf("WSACleanup faild: %d\n", WSAGetLastError());
        return false;
    }
 
    return true;
}
 
// 监听客户端连接
void connectToHost()
{
    // 创建server socket套接字 地址、端口号,AF_INET是IPV4
    SOCKET serfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    if (INVALID_SOCKET == serfd)
    {
        printf("socket faild:%d", WSAGetLastError());
        return;
    }
 
    // 给socket绑定IP地址和端口号
    struct sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(SPORT);                       // htons把本地字节序转为网络字节序
    serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 服务器的IP地址
 
    // 连接到服务器
    if (0 != connect(serfd, (struct sockaddr*)&serAddr, sizeof(serAddr)))
    {
        printf("connect faild:%d", WSAGetLastError());
        return;
    }
 
    printf("连接成功!\n");
 
    while (1)
    {    
        int flag;
        printf("请你选择是要接受文件还是选择结束\n");
        printf("***************************************\n");
        printf("1.传输文件给服务端\n");
        printf("2.从服务端取文件\n");
        printf("3.退出程序\n");
        printf("***************************************\n");
        do {
            scanf_s("%d", &flag);
        } while (!(flag == 1 || flag == 2 || flag == 3));
        system("cls");
        if (flag == 1)
        {
            printf("现在开始向服务端传输文件");
            clientReadySend(serfd);
            while(processMag(serfd))
            {}
        }
        else if(flag == 2)
        {
            printf("现在客户端开始接收文件\n");
            downloadFileName(serfd);// 开始处理消息,100为发送消息间隔
            while (processMag(serfd))
            {}
        }
        else
        {
            printf("系统要退出了...\n");
            closesocket(serfd);
            return false;
        }
        printf("\nPress Any Key To Continue:");
        _getch();
        system("cls");
    }
}
 
// 处理消息
bool processMag(SOCKET serfd)
{
 
    recv(serfd, g_recvBuf, 1024, 0);                     // 收到消息   
    struct MsgHeader* msg = (struct MsgHeader*)g_recvBuf;
 
    /*
    *MSG_FILENAME       = 1,       // 文件名称                服务器使用
    *MSG_FILESIZE       = 2,       // 文件大小                客户端使用
    *MSG_READY_READ     = 3,       // 准备接受                客户端使用
    *MSG_SENDFILE       = 4,       // 发送                    服务器使用
    *MSG_SUCCESSED      = 5,       // 传输完成                两者都使用
    *MSG_OPENFILE_FAILD = 6        // 告诉客户端文件找不到    客户端使用
    */
 
    switch (msg->msgID)
    {
    case MSG_OPENFILE_FAILD:         // 6
        downloadFileName(serfd);
        break;
    case MSG_FILESIZE:               // 2  第一次接收
        readyread(serfd, msg);
        break;
    case MSG_READY_READ:             // 3
        writeFile(serfd, msg);
        break;
    case MSG_SUCCESSED:              // 5
        printf("传输完成!\n");
   
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值