c语言实现FTP

2023-05-16

这个实现了客户端和服务端文件的相互传输(只在本机上运行过),如果是要两台计算机相互传数据要改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");
        return false;
        break;
    case MSG_SERVERREAD:
        printf("准备传输完成");
        sendFile(serfd, msg);
        break;
    }
    return true;
}
 
void downloadFileName(SOCKET serfd)
{
    char fileName[1024];
    struct MsgHeader file;
 
    printf("输入下载的文件名:");
 
    scanf("%s", fileName);                              // 输入文件路径               
    file.msgID = MSG_FILENAME;                               // MSG_FILENAME = 1
    strcpy(file.fileInfo.fileName, fileName);
    send(serfd, (char*)&file, sizeof(struct MsgHeader), 0);  // 发送、IP地址、内容、长度    第一次发送给服务器
}
 
void readyread(SOCKET serfd, struct MsgHeader* pmsg)
{
    // 准备内存 pmsg->fileInfo.fileSize
    g_fileSize = pmsg->fileInfo.fileSize;
    strcpy(g_fileName, pmsg->fileInfo.fileName);
 
    g_fileBuf = calloc(g_fileSize + 1, sizeof(char));         // 申请空间
 
    if (g_fileBuf == NULL)
    {
        printf("申请内存失败\n");
    }
    else
    {
        struct MsgHeader msg;  // MSG_SENDFILE = 4
        msg.msgID = MSG_SENDFILE;
 
        if (SOCKET_ERROR == send(serfd, (char*)&msg, sizeof(struct MsgHeader), 0))   // 第二次发送
        {
            printf("客户端 send error: %d\n", WSAGetLastError());
            return;
        }
    }
 
    printf("size:%d  filename:%s\n", pmsg->fileInfo.fileSize, pmsg->fileInfo.fileName);
}
 
bool writeFile(SOCKET serfd, struct MsgHeader* pmsg)
{
    if (g_fileBuf == NULL)
    {
        return false;
    }
 
    int nStart = pmsg->packet.nStart;
    int nsize = pmsg->packet.nsize;
 
    memcpy(g_fileBuf + nStart, pmsg->packet.buf, nsize);    // strncmpy一样
    printf("packet size:%d %d\n", nStart + nsize, g_fileSize);
 
    if (nStart + nsize >= g_fileSize)                       // 判断数据是否发完数据
    {
        FILE* pwrite;
        struct MsgHeader msg;
 
        pwrite = fopen(g_fileName, "wb");
        msg.msgID = MSG_SUCCESSED;
 
        if (pwrite == NULL)
        {
            printf("write file error...\n");
            return false;
        }
 
        fwrite(g_fileBuf, sizeof(char), g_fileSize, pwrite);
        fclose(pwrite);
 
        free(g_fileBuf);
        g_fileBuf = NULL;
 
        send(serfd, (char*)&msg, sizeof(struct MsgHeader), 0);
 
        return false;
    }
 
    return true;
}
 
void  clientReadySend(SOCKET serfd)
{
    struct MsgHeader msg;
    msg.msgID = MSG_CLIENTREADSENT;
    char fileName[1024] = { 0 };
    printf("请输入要上传的文件名:");
    scanf("%s", fileName);
    FILE* pread = fopen(fileName, "rb");
 
    fseek(pread, 0, SEEK_END);
    g_fileSize = ftell(pread);
    fseek(pread, 0, SEEK_SET);
 
    strcpy(msg.fileInfo.fileName, fileName);
    msg.fileInfo.fileSize = g_fileSize;
 
    send(serfd, (char*)&msg, sizeof(struct MsgHeader), 0);
    g_fileBuf = calloc(g_fileSize + 1, sizeof(char));
 
    if (g_fileBuf == NULL)
    {
        printf("内存不足,重试\n");
    }
 
    fread(g_fileBuf, sizeof(char), g_fileSize, pread);
    g_fileBuf[g_fileSize] = '\0';
 
    fclose(pread);
}
 
 
bool sendFile(SOCKET serfd, struct MsgHeader* pms)
{
    struct MsgHeader msg;                                                     // 告诉客户端准备接收文件
    msg.msgID = MSG_CLIENTSENT;
 
    // 如果文件的长度大于每个数据包能传送的大小(1012),那么久分块
    for (size_t i = 0; i < g_fileSize; i += PACKET_SIZE)                       // PACKET_SIZE = 1012
    {
        msg.packet.nStart = i;
 
        // 包的大小大于总数据的大小
        if (i + PACKET_SIZE + 1 > g_fileSize)
        {
            msg.packet.nsize = g_fileSize - i;
        }
        else
        {
            msg.packet.nsize = PACKET_SIZE;
        }
 
        memcpy(msg.packet.buf, g_fileBuf + msg.packet.nStart, msg.packet.nsize);
 
        if (SOCKET_ERROR == send(serfd, (char*)&msg, sizeof(struct MsgHeader), 0))  // 告诉客户端可以发送
        {
            printf("文件发送失败:%d\n", WSAGetLastError());
        }
    }
 
    return true;
}


服务端头文件

ftpserver.h

#pragma once
#include <stdbool.h>
#include <WinSock2.h>
#include <string.h>
#pragma comment(lib,"ws2_32.lib")  // 加载静态库
 
#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 listenToClient();
 
// 处理消息
bool processMag(SOCKET clifd);
 
// 读取文件,获得文件大小
bool readFile(SOCKET, struct MsgHeader*);
 
// 发送文件
bool sendFile(SOCKET, struct MsgHeader*);
 
//接收文件名和文件大小,创建空间
void serverReady(SOCKET, struct MsgHeader*);
 
//开始写文件
bool writeFile(SOCKET , struct MsgHeader* );


服务端.c文件

ftpserver.c

#include <stdio.h>
#include "ftpserver.h"
 
char g_recvBuf[1024] = { 0 };      // 用来接收客户端消息
int g_fileSize;                    // 文件大小
char* g_fileBuf;                   // 储存文件
char g_fileName[256];
int main(void)
{
    initSocket();
 
    listenToClient();
 
    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 listenToClient()
{
    // 创建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 = ADDR_ANY;     // 监听本机所有网卡
 
    if (0 != bind(serfd, (struct sockaddr*)&serAddr, sizeof(serAddr)))
    {
        printf("bind faild:%d", WSAGetLastError());
        return;
    }
 
    // 监听客户端连接
    if (0 != listen(serfd, 10))                  // 10为队列最大数
    {
        printf("listen faild:%d", WSAGetLastError());
        return;
    }
 
    // 有客户端连接,接受连接
    struct sockaddr_in cliAddr;
    int len = sizeof(cliAddr);
 
    SOCKET clifd = accept(serfd, (struct sockaddr*)&cliAddr, &len);
 
    if (INVALID_SOCKET == clifd)
    {
        printf("accept faild:%d", WSAGetLastError());
        return;
    }
 
    printf("接受成功!\n");
 
        // 开始处理消息
 
 
        while (processMag(clifd))
        {
            Sleep(200);
        }
 
}
 
// 处理消息
bool processMag(SOCKET clifd)
{
    // 成功接收消息返回收到的字节数,否则返回0
    int nRes = recv(clifd, g_recvBuf, 1024, 0);         // 接收
 
    if (nRes <= 0)
    {
        printf("客户端下线...%d", WSAGetLastError());
        return false;
    }
 
    // 获取接受的的消息
    struct MsgHeader* msg = (struct MsgHeader*)g_recvBuf;
    struct MsgHeader exitmsg;
 
    /*
    *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_FILENAME:          // 1  第一次接收
        printf("%s\n", msg->fileInfo.fileName);
        readFile(clifd, msg);
        break;
    case MSG_SENDFILE:          // 4
        sendFile(clifd, msg);
        break;
    case MSG_SUCCESSED:         // 5
 
        exitmsg.msgID = MSG_SUCCESSED;
 
        if (SOCKET_ERROR == send(clifd, (char*)&exitmsg, sizeof(struct MsgHeader), 0))   //失败发送给客户端
        {
            printf("send faild: %d\n", WSAGetLastError());
            return false;
        }
        printf("完成!\n");
        break;
    case MSG_CLIENTREADSENT: //7
        serverReady(clifd, msg);
        break;
    case MSG_CLIENTSENT:
        writeFile(clifd, msg);
        break;
 
    }
    return true;
}
 
/*
*1.客户端请求下载文件 —把文件名发送给服务器
*2.服务器接收客户端发送的文件名 —根据文件名找到文件,把文件大小发送给客户端
*3.客户端接收到文件大小—准备开始接受,开辟内存  准备完成要告诉服务器可以发送了
*4.服务器接受的开始发送的指令开始发送
*5.开始接收数据,存起来     接受完成,告诉服务器接收完成
*6.关闭连接
*/
 
bool readFile(SOCKET clifd, struct MsgHeader* pmsg)
{
    FILE* pread = fopen(pmsg->fileInfo.fileName, "rb");
 
    if (pread == NULL)
    {
        printf("找不到[%s]文件...\n", pmsg->fileInfo.fileName);
 
        struct MsgHeader msg;
        msg.msgID = MSG_OPENFILE_FAILD;                                             // MSG_OPENFILE_FAILD = 6
 
        if (SOCKET_ERROR == send(clifd, (char*)&msg, sizeof(struct MsgHeader), 0))   // 失败发送给客户端
        {
            printf("send faild: %d\n", WSAGetLastError());
        }
 
        return false;
    }
 
    // 获取文件大小
    fseek(pread, 0, SEEK_END);
    g_fileSize = ftell(pread);
    fseek(pread, 0, SEEK_SET);
 
    // 把文件大小发给客户端
    char text[100];
    char tfname[200] = { 0 };
    struct MsgHeader msg;
 
    msg.msgID = MSG_FILESIZE;                                       // MSG_FILESIZE = 2
    msg.fileInfo.fileSize = g_fileSize;
 
    _splitpath(pmsg->fileInfo.fileName, NULL, NULL, tfname, text);  //只需要最后的名字加后缀
 
    strcat(tfname, text);
    strcpy(msg.fileInfo.fileName, tfname);
 
    send(clifd, (char*)&msg, sizeof(struct MsgHeader), 0);            // 文件名和后缀、文件大小发回客户端  第一次发送给客户端
 
    //读写文件内容
    g_fileBuf = calloc(g_fileSize + 1, sizeof(char));
 
    if (g_fileBuf == NULL)
    {
        printf("内存不足,重试\n");
        return false;
    }
 
    fread(g_fileBuf, sizeof(char), g_fileSize, pread);
    g_fileBuf[g_fileSize] = '\0';
 
    fclose(pread);
    return true;
}
 
bool sendFile(SOCKET clifd, struct MsgHeader* pms)
{
    struct MsgHeader msg;                                                     // 告诉客户端准备接收文件
    msg.msgID = MSG_READY_READ;
 
    // 如果文件的长度大于每个数据包能传送的大小(1012),那么久分块
    for (size_t i = 0; i < g_fileSize; i += PACKET_SIZE)                       // PACKET_SIZE = 1012
    {
        msg.packet.nStart = i;
 
        // 包的大小大于总数据的大小
        if (i + PACKET_SIZE + 1 > g_fileSize)
        {
            msg.packet.nsize = g_fileSize - i;
        }
        else
        {
            msg.packet.nsize = PACKET_SIZE;
        }
 
        memcpy(msg.packet.buf, g_fileBuf + msg.packet.nStart, msg.packet.nsize);
 
        if (SOCKET_ERROR == send(clifd, (char*)&msg, sizeof(struct MsgHeader), 0))  // 告诉客户端可以发送
        {
            printf("文件发送失败:%d\n", WSAGetLastError());
        }
    }
 
    return true;
}
 
void serverReady(SOCKET clifd, struct MsgHeader* pmsg)
{
    g_fileSize = pmsg->fileInfo.fileSize;
    char text[100];
    char tfname[200] = { 0 };
 
    _splitpath(pmsg->fileInfo.fileName, NULL, NULL, tfname, text);  //只需要最后的名字加后缀
 
    strcat(tfname, text);
    strcpy(g_fileName, tfname);
    g_fileBuf = calloc(g_fileSize + 1, sizeof(char));         // 申请空间
 
    if (g_fileBuf == NULL)
    {
        printf("申请内存失败\n");
    }
    else
    {
        struct MsgHeader msg;  
        msg.msgID = MSG_SERVERREAD;
 
        if (SOCKET_ERROR == send(clifd, (struct MsgHeader*)&msg, sizeof(struct MsgHeader), 0))   // 第二次发送
        {
            printf("客户端 send error: %d\n", WSAGetLastError());
            return;
        }
    }
 
    printf("filename:%s    size:%d  \n", pmsg->fileInfo.fileName, pmsg->fileInfo.fileSize);
}
 
bool writeFile(SOCKET clifd, struct MsgHeader* pmsg)
{
    if (g_fileBuf == NULL)
    {
        return false;
    }
 
    int nStart = pmsg->packet.nStart;
    int nsize = pmsg->packet.nsize;
 
    memcpy(g_fileBuf + nStart, pmsg->packet.buf, nsize);    // strncmpy一样
    printf("packet size:%d %d\n", nStart + nsize, g_fileSize);
 
    if (nStart + nsize >= g_fileSize)                       // 判断数据是否发完数据
    {
        FILE* pwrite;
        struct MsgHeader msg;
 
        pwrite = fopen(g_fileName, "wb");
        msg.msgID = MSG_SUCCESSED;
 
        if (pwrite == NULL)
        {
            printf("write file error...\n");
            return false;
        }
 
        fwrite(g_fileBuf, sizeof(char), g_fileSize, pwrite);
        fclose(pwrite);
 
        free(g_fileBuf);
        g_fileBuf = NULL;
 
        send(clifd, (char*)&msg, sizeof(struct MsgHeader), 0);
 
        return false;
    }
 
    return true;
}


代码写的很粗糙,很多地方都没有注释大家看着玩就好了。

下面是我的一些对于实现c语言socket编程的一些函数总结:

服务器先启动

Socket是初始化socket库         

先对TCP服务端建立一个服务端的socket 

socket(int domain,int type,int protocol)函数   只是声明这个socket是什么类型的

1.domain:协议域,常见的协议组用AF_INET AF_INET6 AF_LOCAL AF_ROUTE . 协议族决定了socket的地址类型,在通信中必须采用相应的地址.

2.type: 指定socket的类型.

  1. 流格式套接字(SOCK_STREAM):也称之为面向连接的套接字
  2. 数据报格式套接字(SOCK_DGRAM):也称之为无连接的套接字

protocol:协议,常见的协议有IPPROTO_TCP、IPPTOTO_UDP、 IPPROTO_SCTP、IPPROTO_TIPC他们分别对应这TCP传输协议,UDP传输协议,STCP传输协议,TIPC传输协议.当protocol为0时,会自动选择type类型对应的默认协议.

bind(int sockfd,const struct* addr,socklen_t  addrlen) 给socket绑定IP地址和端口号

1.sockfd:即为socket描述字,他是通过socket()函数创建的,唯一标识一个socket.bind函数就是将这个描述子绑定一个名字

2.addr:一个const struct sockaddr*指针,根据创建地址结构根据地址创建socket时的地址协议不同而不同.

    struct sockaddr_in serAddr; 先在serAddr里面进行绑定协议族、端口、IP

3.addrlen:对应地址的长度.通常服务器在启动时会绑定一个总所周知的地址(ip地址+端口号),客户端不用指定系统自动分配,所以通常服务端在listen之前要调用bind(),而客户端不会调用,在connect()时由系统随机生成一个.

       大小一般为sizeof(serAddr)

将地址绑定到一个socket时,需要将主机字节序转换为网络字节序。

主机字节学是指处理器存储数据的字节顺序 Inter x86是不重要保存在低地址,重要部分保存在高地址

网络字节序是重要部分保存在低地址,不重要部分保存在高地址

listenint sockfdint backlog

listen函数的第一个参数时即将要监听的socket描述字,第二个参数为相应的socket可以排队的最大连接数。socket()创建的socket默认是一个主动类型,listen则将socket变成被动类型,等待客户连接请求。

connectint sockfdconst struct sockaddr *addrsocklen_t addrlen

connect函数的第一个参数是客户端socket的描述,第二个参数是socket的地址,第三个函数是socket的地址的长度。客户端通过调用connect函数建立与TCP服务器的连接。

accept(int sockfd,struct sockaddr *addr , socklen_t addrlen)

accept函数的第一个函数为服务器端的socket描述字,是服务器一开始调动socket()函数产生的,而accept函数返回的是已经连接的socket描述字。第二个参数用于返回客户端的协议地址,第三个表示地址的长度

编译软件用的是visual studio2022

在敲代码中遇到的一些问题:

1.有些地方会警告报错,要在视图中找到属性页,然后将C/C++常规中的SDL改为否

2.gets_s函数会造成缓冲区的一些泄露(这个地方我也不是很懂)在地址读取的时候我换的是scanf_s函数
 

这个程序用了比较多的技巧,要对c语言有一定的理解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c语言实现FTP 的相关文章

  • PHP ftp_put 返回“无法建立数据连接:连接被拒绝”

    我有一台通过 PHP 运行一些 FTP 的 PC 我知道它在 1 2 个月前还可以工作 但现在我返回它 发现该 PC 不再工作了 我知道我一直在使用电脑 但我想不出可能会发生什么变化 PHP 抛出错误消息读取 无法建立数据连接 连接被拒绝
  • 让 FTP 在 Azure VM 上运行,克服 ftp 客户端上的“连接关闭”问题

    我正在努力连接到 Azure 中新 VM 上的 FTP 我从默认映像 Windows Server 2012 Datacenter 创建了一个新的虚拟机 并通过 RDP 连接到新的虚拟机中 然后 我启用了 Web 服务器 IIS 角色 包括
  • 使用 PowerShell 重命名 FTP 上的文件

    有没有办法重命名 FTP 目录中的文件 我正在将实时图像从计算机流式传输到 FTP 但问题是当它将图像上传到 FTP 时 它会立即替换文件 我想先上传临时名称的图像 然后重命名为 live jpg 这就像缓存文件上传一样 while tru
  • ftp 在 java 中无法正确下载文件?

    当我使用以下代码下载文件时 它只是将文件写入本地目的地 但文件大小均为零 有人能说为什么会发生这种情况以及如何解决它吗 import org apache commons net ftp FTPClient import org apach
  • 紧凑框架 - OpenNetCf.Net FTP 示例?

    我正在尝试让 OpenNetCF Net FTP 组件与我的 PDA 应用程序一起工作 除了连接到服务器之外 我正在努力让它做更多的事情 并且想知道是否有人知道我可以用来学习如何使用它的任何示例代码 我需要能够下载和上传文件 以及确定我想要
  • 选择 FTP 和 HTTP 传输的缓冲区大小

    在实现低级 HTTP 和 FTP 传输时 如何选择缓冲区的大小 从套接字读取或写入套接字的字节数 以获得最大吞吐量 我的应用程序应该在 130 Kbps 到 3 Mbps 的连接上使用 HTTP 或 FTP 传输数据 我事先知道预期的速度
  • 如何使用 php 检查 smtp 服务器是否正常工作

    我想使用 php 检查我的网站 smtp 是关闭还是开启 我尝试使用 fsockopen 连接到服务器上的端口 25 然后当 smtp 服务运行时它返回 true 这是使用 php 脚本测试 smtp 或 ftp 是否运行的最佳方法 您正在
  • php ftp 建立多个目录

    这是我的 PHP 代码 它实际上工作得很好 newftpdir parent date Ymd YYYYMMDD newftpdir child ext folder username newftpdir newftpdir parent
  • 是否可以通过 FTP 代理使用 C# FtpWebRequest?

    据我了解 FtpWebRequest Proxy属性表示 HTTP 代理 我必须通过 FTP 代理向外部服务器发出 FTP 请求 到目前为止 我实现此功能的唯一方法是创建一个使用 Windows FTP 命令的脚本并以这种方式下载 是否可以
  • 使用.net 2.0 连接到 FTP 服务器 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我希望连接到现有的 FTP 服务器 上传文件 等待服务器生成报告 然后将该报告下载回 VB NET 2
  • Curl 同时下载和上传同一文件

    不确定是否可能 但我一直在尝试使用curl 从 HTTP 位置下载文件并将其输出到 FTP 服务器上 如果这实际上可能的话 我真的很希望得到一些帮助 curl http example com down curl T ftp mysite
  • 使用 .NET 进行选择性 FTP 下载

    我有一个 ftp 构建站点 新构建将在其中更新 它将在每个新构建的特定 ftp 位置创建一个名为 Build XXXXX 的新文件夹 我需要从 Build XXXXX 目录中的某个位置下载构建版本 例如 Builds Build XXXXX
  • 从 C# 中的服务器下载后,Zip 文件被损坏

    request MakeConnection uri WebRequestMethods Ftp DownloadFile username password response FtpWebResponse request GetRespo
  • 考虑到每次轮询最大消息数和 Cron,轮询如何用于 FTP 入站通道适配器

    我有 UC 我需要从 ftp 位置选取文件并将其放入服务器位置 我正在使用 ftp inbound channel adapter Spring 集成 2 0 4 来实现它 下面是我的xml中的配置
  • Twisted、FTP 和“流式传输”大文件

    我正在尝试实现最能描述为 HTTP API 的 FTP 接口 的内容 本质上 有一个现有的 REST API 可用于管理站点的用户文件 并且我正在构建一个中介服务器 将该 API 重新公开为 FTP 服务器 因此 您可以使用 Filezil
  • 通过 FTP over TLS/SSL 连接到未经认证的主机

    我从中获取文件的供应商正在从 FTP 更改为基于 SSL 的 FTP 我正在尝试更新我的代码net ftp to net ftptls 我需要连接的新主机未经认证 我的脚本报告此错误 主机名与服务器证书不匹配 供应商不会修复此问题 看着 u
  • PHP + FTP删除文件夹中的文件

    我刚刚编写了一个 PHP 脚本 它应该连接到 FTP 并删除特殊文件夹中的所有文件 它看起来像这样 但我不知道需要什么命令来删除文件夹日志中的所有文件 任何想法
  • 使用 Python ftplib 获取远程 FTP 服务器中文件的 MD5 值

    使用 ftplib 将文件传输到服务器后 如何确定该文件与本地服务器中的文件的 MD5 from ftplib import FTP import hashlib ftp FTP server ftp login username pass
  • 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同

    System Net WebException 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同 在 System Net FtpWebRequest CheckError 在 System Net FtpWebReque
  • FTP 下载冻结整个应用程序

    我正在尝试从 FTP 服务器下载一个大约 100 MB 的文件 这是一个测试 bin 文件 因为我正在测试该应用程序 我猜我将来想要下载的文件会更重 当我想下载文件时 整个应用程序就会冻结 几秒钟后它就会下载文件 该文件已完成 并且已成功下

随机推荐

  • OpenCV-python学习笔记(十二)——图像轮廓

    十二 图像轮廓 图像轮廓是指将边缘连接起来形成的一个整体 xff0c 用于后续的计算 因为边缘检测得到的边缘是不连续的 查找图像内的轮廓信息 xff1a cv2 findContours 绘制轮廓 xff1a cv2 drawContour
  • k210——maix bit串口通信

    k210 串口通信 k210 一共有3个 uart xff0c 每个 uart 可以进行自由的引脚映射 一 API函数介绍 1 1 register pin function force 61 True K210 可以通过映射来改变引脚功能
  • k210——Maixhub 云端模型训练

    k210 Maixhub 云端模型训练 一 前言 k210的模型训练可以在Maixhub 上进行 xff0c 只需要准备好需要训练的数据集 xff0c 不需要搭建训练环境和代码 xff0c 上传训练数据即可快速训练出模型 Maixhub 有
  • 自动控制原理MATLAB常用函数总结

    自动控制原理MATLAB常用函数总结 一 控制系统的数学模型 1 传递函数数学模型 G xff08 s xff09 61
  • MCS-51汇编软件实验

    MCS 51汇编软件实验 实验一 内存块移动 将指定源地址和长度的存储块移到指定目标地址为起始地址的单元中去 移动3000H起始的256个字节到4000H起始的256个字节 代码示例 xff1a ORG 0000H MOV DPTR 300
  • Jmeter性能测试(9)--逻辑控制器

    jmeter中逻辑控制器 xff08 Logic Controllers xff09 的作用域只对其子节点的sampler有效 xff0c 作用是控制采样器的执行顺序 jmeter提供了17种逻辑控制器 xff0c 它们各个功能都不尽相同
  • MapReduce的工作流程:map和reduce分别做了哪些工作,以及shuffle机制实现了什么

    一 map和reduce分别做了哪些工作 Map 待处理数据分片放入缓冲区 xff0c 分区 排序 合并 归并 xff0c 写入本地磁盘 将处理杂乱无章的数据 xff0c 找出规律 xff0c 归纳处理 1 读取hdfs上的文件 xff0c
  • Prometheus监控部署

    文章目录 一 通用监控系统基础知识以及Prometheus的概述1 监控系统的发展史 xff1a 2 什么是Prometheus 二 工作原理及适用性1 prometheus获取数据的方式 三 xff0c 实验环境1 关闭防火墙和核心防护P
  • Docker之 神操作!居然能修改已运行的 Docker 容器端口映射

    文章目录 一 容器未启动 xff1f 二 容器已启动 xff1f 2 1 但是想修改或者添加端口时 xff0c 先停止掉正在运行的容器 2 2 查看容器完整的 96 hash of the container 96 数值 xff1a 2 3
  • python版MapReduce基础实战

    第一关 xff1a 成绩统计 任务描述 本关任务 xff1a 使用Map Reduce计算班级中年龄最大的学生 相关知识 为了完成本关任务 xff0c 你需要掌握 xff1a 1 什么是MapReduce xff0c 2 如何使用MapRe
  • 视觉SLAM十四讲笔记六(第七讲)

    1 引言 前几节介绍了运动方程和观测方程的具体形式 xff0c 并讲解了以非线性优化为 主的求解方法 本讲 xff0c 我们将介绍什么是特征点 xff0c 如何提取和匹配特征点 xff0c 以及如何根据配对的特征点估计相机运动 2 特征点法
  • [C++教程①]--了解c语言以及第一行代码

    hellohello xff0c 我是离 今天开始 xff0c 我会对小白朋友讲解c 43 43 C 43 43 是什么 C 43 43 是C语言的继承 xff0c 它既可以进行C语言的过程化程序设计 xff0c 又可以进行以抽象数据类型为
  • 虚拟机可以ping通IP,但是ping通不了域名

    今天用VMware安装了一个centos7系统 xff0c 正常安装上去 xff0c 编辑了ifcfg ens33网卡信息 在物理机上ping虚拟机地址和百度的域名 xff0c 测试可以ping通 又去虚拟机上ping一下百度域名www b
  • 笔记(STM32篇)day12——USART串口介绍、串口初始化结构体

    目录 一 USART介绍 1 USART简介 2 USART功能框图 二 串口初始化结构体 参考 一 USART介绍 1 USART简介 通用同步异步收发器 Universal Synchronous Asynchronous Receiv
  • 京东Java后台开发岗社招面试经验分享,4面的面经!

    前言 正好最近我一朋友面试京东回来 xff0c 和我聊了他的面试经过 xff0c 最后经过四面成功斩获offer xff01 下面我把他所得经验毫无保留的分享给大家 xff01 希望对正准备面试小伙伴们能有所帮助 xff01 xff01 x
  • 关于系统架构

    系统架构 1 系统架构包括什么形式2 C S架构2 1 C S架构的软件或者系统2 2 C S架构的特点2 3 C S架构的优缺点 3 B S架构3 1 优缺点3 2 B S结构的系统的通信原理关于域名 4 WEB服务器软件4 1 WEB服
  • Jmeter性能测试(10)--参数化

    参数化是自动化测试脚本的一种常用技巧 简单来说 xff0c 参数化的一般用法就是将脚本中的某些输入使用参数来代替 xff0c 在脚本运行时指定参数的取值范围和规则 xff1b 这样 xff0c 脚本在运行时就可以根据需要选取不同的参数值作为
  • AT指令1

    我之前认为手机号码与SIM卡是一一对应的 xff0c 后来想想不对 xff0c 因为有换卡不换号的情况啊 xff0c 所以SIM卡应该只是一个电话号码的储存介质 xff0c 而与SIM卡一一对应的是另一个编码 IMSI xff08 国际移动
  • Keil5 的常见错误

    1 C Source led c 22 warning 69 D integer conversion resulted in truncation 这个是由于实际值的范围超过了定义值的范围 2 C Source main c 15 err
  • c语言实现FTP

    这个实现了客户端和服务端文件的相互传输 xff08 只在本机上运行过 xff09 xff0c 如果是要两台计算机相互传数据要改ip 给大家看一下实现过程 xff08 exe文件要先开服务端的 xff09 输入1 直接将快捷方式拖拽上去就有绝