Analysis of file uploading process for Distributed File system Fastdfs source code Analysis

Source: Internet
Author: User
Tags int size sendfile htons

Fastdfs is a lightweight, distributed file system, consisting primarily of tracker server, storage server, and client, which mainly involves two points:
1 Client upload file process and protocol analysis
2 implementation of a simple file upload function

One: The basic process of file upload

Fastdfs upload a file, mainly involves the following several steps:

1 Upload the connection request, the client will send the request of uploading file to tracker server
2 Tracker after receiving the request, return the IP and port of storage server
3 Client connection storage, and upload file
4 after the completion of the file upload, storage return path information

The following detailed analysis of the file upload process of the protocol and various operations

Fastdfs protocol head:

typedef struct
    {
        char pkg_len[fdfs_proto_pkg_len_size];  Body length, not including header (8 bytes)
        char cmd;    Command code     tracker_proto_cmd_service_query_store_without_group_one
        char status;//status code for Response
    } Trackerheader;

The head of the FASTDFS protocol is composed of a 10-byte structure,
Send: Send the data, first send Trackerheader to the server, then send the specific data
Acceptance: Accept the data, first accept the sizeof (Trackerheader) size of the message head, and then accept the Pkg_len length of the report style

Status: Set to 0 when sent
CMD: command
Pkg_len: A int64_t integral type that removes the length of the message Trackerheader length

Two: The client sends the storage address request to the tracker server
#define Tracker_proto_cmd_service_query_store_without_group_one

Protocol head//Pkg_len | cmd | Status//8 bytes | 1 bytes |

    1 bytes//request to TRACKER Server storage server cmd #define TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE 101
    Trackerheader header;//Protocol Head memset (&header, 0, sizeof (trackerheader));

    Header.cmd = Tracker_proto_cmd_service_query_store_without_group_one; Request Storage,tcpsenddata return non 0 to tracker server to send success if (Tcpsenddata sockfd, &header, sizeof (Trackerheader), &A
        Mp;count)!= 0) {fprintf (stderr, "Tcpsenddata Error:%s\n", Strerror (errno));
    return 1;
        else//request sent successfully, waiting for tracker reply {///Receive Head, head is a trackerheader type, 10 bytes Trackerheader resp; if ((Ret_code = Tcprecvdata (sockfd, &resp, sizeof (Trackerheader), &count))!= 0) {fprintf
            (stderr, "Tcprecvdata Error:%s\n", Strerror (Ret_code));
        return 1;
//start receiving newspaper stylistic//int64_t Read_int64 (const char *buff)        {//unsigned char *p;
        p = (unsigned char *) buff; Return (((int64_t) (*p)) << 56) |  \//((int64_t) (* (p+1)) << 48) |  \//((int64_t) (* (p+2)) << 40) |  \//((int64_t) (* (p+3)) << 32) |  \//((int64_t) (* (p+4)) << 24) |  \//((int64_t) (* (p+5)) << 16) | \//((int64_t) (* (p+6)) << 8) |
        \//((int64_t) (* (p+7));

        int size = Read_int64 (Resp.pkg_len);//Get the body length char *buf = (char*) calloc (size + 1, sizeof (char)); if ((Ret_code = Tcprecvdata (SOCKFD, buf, size, &count)!= 0)) {fprintf (stderr, "Tcprecvda")
            TA error:%s\n ", Strerror (Ret_code));
        return 1; }//Newspaper style//group_name |ip |port |storage_index/bytes |16 bytes |8 b
        Ytes | #define Tracker_query_storaGe_store_body_len-if (count!= tracker_query_storage_store_body_len) {fprintf (stderr, "Inva
            Lid message ");
        return 1;  }//group name//#define Fdfs_group_name_max_len Char Group_name[fdfs_group_name_max_len +
        1] = {0};
        memcpy (Group_name, buf, Fdfs_group_name_max_len);
        Group_name[fdfs_group_name_max_len] = ' the ';
        Ip:port//#define ip_address_size//port:8 bytes Char ip[ip_address_size + 1] = {0};
        memcpy (IP, buf + fdfs_group_name_max_len, ip_address_size-1);
        Char Szport[8] = {0};
        memcpy (Szport, buf + Fdfs_group_name_max_len + ip_address_size-1, 8);
        Ip[ip_address_size] = ' the ';
        int port = Read_int64 (Szport);
        Storage index;

 Char *storage_index = buf + Fdfs_group_name_max_len + ip_address_size-1 + fdfs_proto_pkg_len_size;

three: After the completion of the above steps, get storage IP and port, you can upload files

In the official client, the file operation has upload,download, Append,delete and so on, here only involves the upload
In the upload file, the official gives three ways
1 through the buffer upload, the file will be read into memory, and then send
2 using Sendfile,sendfile is a library function provided by Linux
3 by means of a callback function

This is mainly concerned with the first kind, by the way of buffer upload

File Upload protocol:

File Upload protocol head
    bytes        | 1 bytes        | 8 bytes    | 6 bytes        |
    Trackerheader   | storage_index |  file length |    filename or all 0)  |
Storage_index is the result//file name returned by the client applying to tracker server storage index If it is
not empty, take the top 6 digits, or you can set it all to 0



//upload complete Storage Reply Client protocol
bytes      | bytes    | Trackerheader.pkg_len-16bytes 
trackerheader | groupname   | remote file name
void UploadFile (int sockfd, const char *filepath, char *storage_index) {char out_buf[512];
    Trackerheader *pheader;
    char *p = out_buf;

    char *buf = NULL; Trackerheader Bytes//File Upload Protocol head//10 bytes | 1 bytes | 8 bytes |
    6 bytes | Trackerheader | Storage_index | File Length |
    FileName or all 0) |
    Pheader = (trackerheader*) out_buf;

    p + + sizeof (Trackerheader);
    Storage index 1 bytes *p++ = *storage_index;
    FileSize 8bytes long int filesize = 0;
    int ret = 0; Reads the file to BUF and returns the file length FileSize if ((ret = Getfilebuf (&buf, &filesize, filepath)!= 0)) {fprintf (stde
        RR, "Getfilebuf failed:%s\n", strerror (ret));
    Return
    }//void Write_int64 (int64_t N, char *buff)//{//unsigned char *p;
    p = (unsigned char *) buff;
    *p++ = (n >> a) & 0xFF;
    *p++ = (n >> a) & 0xFF;
    *p++ = (n >>) & 0xFF; *p++ = (n >>) & 0xFF;
    *p++ = (n >>) & 0xFF;
    *p++ = (n >>) & 0xFF;
    *p++ = (n >> 8) & 0xFF;
    *p++ = n & 0xFF;
    } write_int64 (FileSize, p);

    #define FDFS_PROTO_PKG_LEN_SIZE 8 p + + fdfs_proto_pkg_len_size;
    Ext_name//#define Fdfs_file_ext_name_max_len 6 memset (p, 0, Fdfs_file_ext_name_max_len);

    p + + Fdfs_file_ext_name_max_len;
    Set Trackerheader Write_int64 (P-out_buf + filesize-sizeof (trackerheader), Pheader->pkg_len);
    #define Storage_proto_cmd_upload_file pheader->cmd = storage_proto_cmd_upload_file;

    Pheader->status = 0;
    Send message head int count;
    int ret_code = 0; if ((Ret_code = Tcpsenddata (SOCKFD, Out_buf, P-out_buf, &count)!= 0)) {fprintf (stderr, "Tcpsenddata FAI
        LED:%s\n ", Strerror (errno));
    Return //Send a report style, specific file data if ((Ret_code = Tcpsenddata (SOCKFD, buf, FileSize, &count))!= 0) {fprintf (stderr, "Tcpsenddata body failed:%s\n", Strerror (errno));
    Return //Receive Storage server reply//upload complete Storage reply client protocol//10 bytes | bytes | Trackerheader.pkg_len-16bytes//trackerheader | GroupName |
    Remote file name Trackerheader resp; if ((Ret_code = Tcprecvdata (sockfd, &resp, sizeof (Trackerheader), 1000, &count))!= 0) {fprintf (stderr, "t
        Cprecvdata failed:%s\n ", Strerror (Ret_code));
    Return
        } if (Count!= sizeof (Trackerheader)) {fprintf (stderr, "Invalid header");
    Return
    } int64_t Bodylen = Read_int64 (Resp.pkg_len);
    Receive newspaper stylistic char *in_buf = (char*) calloc (Bodylen + 1, sizeof (char)); if ((Ret_code = Tcprecvdata (SOCKFD, In_buf, Bodylen, &count))!= 0) {fprintf (stderr, "read Body Faile
        D:%s\n ", Strerror (Ret_code));
    Return //groupname//#define Fdfs_group_name_max_len Char Group_name[fdfs_group_name_mAx_len + 1];
    memcpy (Group_name, In_buf, Fdfs_group_name_max_len);

    Group_name[fdfs_group_name_max_len] = ' the ';
    Remote filename char Remote_filename[bodylen-fdfs_group_name_max_len + 1];

    memcpy (remote_filename, In_buf + fdfs_group_name_max_len, Bodylen-fdfs_group_name_max_len + 1);
    cout << "groupname:" << group_name << Endl;

    cout << "Remote_filename:" << remote_filename << Endl;
    Char httpaddr[128] = {0};
    sprintf (httpaddr, "http://106.75.129.177:8080/%s/%s", Group_name, Remote_filename); cout << "httpaddr:" << httpaddr << endl;//http Address}

The following is enclosed with complete code, UBUNTU14 bit, compiler g++, test passed

#include <iostream> #include <sys/socket.h> #include <arpa/inet.h> #include <errno.h> #include
<unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h>
using namespace Std; #define FDFS_GROUP_NAME_MAX_LEN #define FDFS_PROTO_PKG_LEN_SIZE 8 #define Ip_address_size//cmd #def INE Tracker_proto_cmd_service_query_store_without_group_one #define Storage_proto_cmd_upload_file #defin  E Tracker_query_storage_store_body_len (Fdfs_group_name_max_len + ip_address_size-1 + FDFS_PROTO_PKG_LEN_SIZE +
    1) #define Fdfs_file_ext_name_max_len 6 typedef struct {char pkg_len[fdfs_proto_pkg_len_size];
    char cmd;
char status;

}trackerheader;
Set SOCKETFD nonblocking int setnonblocking (int sockfd);
int tcprecvdata (int sockfd, void *data, const int size,\ const int Timeout_ms, int *count); int tcpsenddata (int sockfd, void *data, const int size,\ const INT timeOut_ms, int *count);
int64_t Read_int64 (const char* BUF);

void Write_int64 (int64_t N, char* buf);
void UploadFile (int sockfd, const char *filepath, char *storage_index);
int Getfilebuf (char **buf, long int *filesize, const char* filepath);
    Apply storage address from Tracker server int main () {const char *IP = "127.0.0.1";
    uint16_t port = 22122;
    int ret_code = 0;
    int sockfd =-1;
    int count = 0; Connect Tracker Server if (SOCKFD = socket (pf_inet, sock_stream, 0)) < 0) {fprintf (stderr, "socket
        Errnor:%s\n ", Strerror (errno));
    return 1; } if ((Ret_code = setnonblocking (sockfd))!= 0) {fprintf (stderr, "setnonblocking Error:%s\n", Strerror (R
        Et_code));
    return 1;
    } struct sockaddr_in addr;
    ADDR.SIN_ADDR.S_ADDR = inet_addr (IP);
    Addr.sin_port = htons (port);

    addr.sin_family = af_inet;
    socklen_t len = sizeof (struct sockaddr); if (Connect (SOCKFD, (struct sockaddr*) &addr, Len) &lT
        0) {fprintf (stderr, "Connect error:%s\n", Strerror (errno));
    return 1;
    } Trackerheader header;
    memset (&header, 0, sizeof (trackerheader));

    Header.cmd = Tracker_proto_cmd_service_query_store_without_group_one; if (Tcpsenddata (SOCKFD, &header, sizeof (Trackerheader), &count)!= 0) {fprintf (stderr, "Tcpsenddat")
        A error:%s\n ", Strerror (errno));
    return 1;
        else {//RECV header Trackerheader resp; if ((Ret_code = Tcprecvdata (sockfd, &resp, sizeof (Trackerheader), &count))!= 0) {fprintf
            (stderr, "Tcprecvdata Error:%s\n", Strerror (Ret_code));
        return 1;

        } cout << "recv header:" << count << Endl;
        Read body;
        int size = Read_int64 (Resp.pkg_len);

        Char *buf = (char*) calloc (size + 1, sizeof (char)); 
   if ((Ret_code = Tcprecvdata (SOCKFD, buf, size, &count)!= 0))     {fprintf (stderr, "Tcprecvdata Error:%s\n", Strerror (Ret_code));
        return 1;     }//body//group_name |ip |port |storage_index//16bytes |16bytes |8bytes
        |
        cout << "read body:" << count << Endl;
            if (count!= tracker_query_storage_store_body_len) {fprintf (stderr, "Invalid message");
        return 1;
        }//group Name char Group_name[fdfs_group_name_max_len + 1] = {0};
        memcpy (Group_name, buf, Fdfs_group_name_max_len);
        Group_name[fdfs_group_name_max_len] = ' the ';
        cout << "group name:" << group_name << Endl;
        Ip:port Char ip[ip_address_size + 1] = {0};
        memcpy (IP, buf + fdfs_group_name_max_len, ip_address_size-1);
        Char Szport[8] = {0};
        memcpy (Szport, buf + Fdfs_group_name_max_len + ip_address_size-1, 8); Ip[ip_address_size] = '';
        int port = Read_int64 (Szport);
        cout << "Address: << IP <<": << Port << Endl;
        Storage index;
        Char *storage_index = buf + Fdfs_group_name_max_len + ip_address_size-1 + fdfs_proto_pkg_len_size;
        cout << "Storage_index:" << storage_index << Endl;

        Free (BUF);
        Connect storage server sockaddr_in st_addr;
        ST_ADDR.SIN_ADDR.S_ADDR = inet_addr (IP);
        st_addr.sin_family = af_inet;

        St_addr.sin_port = htons (port);
        int STORAGE_FD = socket (af_inet, sock_stream, 0);
            if (STORAGE_FD < 0) {fprintf (stderr, "Socket failed:%s\n", Strerror (errno));
        return 1;
        } socklen_t len2 = sizeof (sockaddr_in);  if (Connect (storage_fd, (struct sockaddr*) &st_addr, Len2) < 0) {fprintf (stderr, "Connect failed:%s\n",
            Strerror (errno));
        return 1; } uploadfile (STORAGE_FD, "1.jpg", Storage_index);
return 0;
    int Getfilebuf (char **buf, long int *filesize, const char *filepath) {int ret_code = 0;
    FILE *FP = fopen (filepath, "rb+");
        if (fp = = NULL) {ret_code = errno;
    return ret_code;
    }//get filesize;
    Fseek (FP, 0, Seek_end);
    *filesize = Ftell (FP);
    Fseek (FP, 0, Seek_set);
    cout << "Get filesize:" <<*filesize << Endl;
    malloc buf *buf = (char*) calloc (*filesize + 1, sizeof (char));
        if (*buf = = NULL) {ret_code = errno;
    return ret_code;
    int read_bytes = 0;
    int left_bytes = *filesize;
    char *p = *buf;
        while (Left_bytes > 0) {read_bytes = Fread (p, sizeof (char), left_bytes, FP);
        Left_bytes-= read_bytes;
    p + + read_bytes;
return ret_code;
    } void UploadFile (int sockfd, const char *filepath, char *storage_index) {char out_buf[512];
    Trackerheader *pheader;
    char *p = out_buf;char *buf = NULL;
    Trackerheader bytes Pheader = (trackerheader*) out_buf;

    p + + sizeof (Trackerheader);
    Storage index 1 bytes *p++ = *storage_index;
    FileSize 8bytes long int filesize = 0;
    int ret = 0; if (ret = Getfilebuf (&buf, &filesize, filepath)!= 0)) {fprintf (stderr, "Getfilebuf failed:%s\n", St
        Rerror (ret));
    Return
    printf ("FileSize:%ld\n", filesize);
    Write_int64 (FileSize, p);

     p + + fdfs_proto_pkg_len_size;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.