The first Erlang program: FTP download Client

Source: Internet
Author: User
Learning about Erlang for one week:

   1 -module(ftp_down).   2 -export([get/6,test/0,get_data/4]).   3    4 test() ->   5     get("ftp.ftpplanet.com", 21, "anonymous", "anonymous", "images/image001_42.jpg", "d:/").   6    7 client_message(Format, Data) ->   8     io:format("C: " ++ Format ++ "~n", Data).   9   10 server_message(Format, Data) ->  11     io:format("S: " ++ Format ++ "~n", Data).  12   13 server_verify_message(Data, ExpectedCode) ->  14     {Code, Message} = Data,  15     ExpectedCode = Code,  16     io:format("S: ~s~n", [Message]),  17     ok.  18   19 recv_until_EOL(Sock, StrSoFar) ->  20     Len = string:len(StrSoFar),  21     NotALine = Len < 2 orelse not string:equal("/r/n", string:substr(StrSoFar, Len - 1, 2)),  22     if  23         NotALine ->  24             {ok, Msg} = gen_tcp:recv(Sock, 1),  25             recv_until_EOL(Sock, StrSoFar ++ Msg);  26         true ->  27             StrSoFar  28     end.  29       30 recv_until_EOL(Sock) ->  31     recv_until_EOL(Sock, "").  32   33 recv_until_xxxend(Sock, Num, Line, LinesSoFar) ->  34     ExpectedTail = integer_to_list(Num) ++ " end",  35     ExpectedTailLen = string:len(ExpectedTail),  36     Pos = string:len(Line) - ExpectedTailLen - 1,  37     Eq = Pos > 0 andalso string:equal(ExpectedTail, string:to_lower(string:substr(Line, Pos, ExpectedTailLen))),  38     if  39         Eq ->  40             {Num, LinesSoFar ++ Line};  41         true ->  42             recv_response(Sock, Num, LinesSoFar ++ Line)  43     end.  44   45 recv_response(Sock, LinesSoFar) ->  46     Line = recv_until_EOL(Sock),  47     {Num, [H | _]} = string:to_integer(Line),  48     if  49         H == $- ->  50             recv_until_xxxend(Sock, Num, Line, LinesSoFar);  51         true ->  52             {Num, LinesSoFar ++ Line}  53     end.  54       55 recv_response(Sock, ResponseNo, LinesSoFar) ->  56     Line = recv_until_EOL(Sock),  57     recv_until_xxxend(Sock, ResponseNo, Line, LinesSoFar).  58       59 recv_response(Sock) ->  60     recv_response(Sock, []).  61   62 send_command(Sock, Msg) ->   63    ok = gen_tcp:send(Sock, Msg ++ "/r/n"),  64    client_message("~s", [Msg]).  65      66 parse_pasv(Msg) ->  67     Index1 = string:chr(Msg, $(),  68     Index2 = string:chr(Msg, $)),  69     [A1, A2, A3, A4, B1, B2] = lists:map(fun(S) -> string:strip(S) end, string:tokens(string:substr(Msg, Index1 + 1, Index2 - Index1 -1), ",")),  70     {Nb1, _} = string:to_integer(B1),  71     {Nb2, _} = string:to_integer(B2),  72     <<Port:16>> = <<Nb1:8, Nb2:8>>,  73     {lists:append([A1, ".", A2, ".", A3, ".", A4]), Port}.  74    75   76 recv_until_transfer_complete(Sock, {ok , Msg}, MsgSoFar) ->  77     if  78         length(Msg) > 0 ->  79             recv_until_transfer_complete(Sock, gen_tcp:recv(Sock, 0), MsgSoFar ++ Msg);  80         true ->  81             receive  82                 transfer_complete ->  83                     MsgSoFar  84                 after 200 ->  85                     recv_until_transfer_complete(Sock, gen_tcp:recv(Sock, 0), MsgSoFar ++ Msg)  86             end  87     end;  88       89   90 recv_until_transfer_complete(_, {error , closed}, MsgSoFar) ->  91     MsgSoFar.  92   93 recv_until_transfer_complete(Sock) ->  94     receive  95         start_transfer ->  96             recv_until_transfer_complete(Sock, gen_tcp:recv(Sock, 0), [])  97         after 30000 ->  98             "150 timeout"  99     end. 100  101 get_data(Addr, Port, LocalFilePath, Control) -> 102     {ok, DataSock} = gen_tcp:connect(Addr, Port, [{active, false}]), 103     Data = recv_until_transfer_complete(DataSock), 104     client_message("<I GOT>: ~w Bytes~n", [length(Data)]), 105     file:write_file(LocalFilePath, list_to_binary(Data)), 106     gen_tcp:close(DataSock), 107     Control ! bye. 108      109      110 get(Host, Port, User, Pass, FilePath, LocalPath) -> 111     Slash = string:rchr(FilePath, $/), 112     Path = string:left(FilePath, Slash - 1), 113     File = string:right(FilePath, string:len(FilePath) - Slash), 114      115     {ok, Sock} = gen_tcp:connect(Host, Port, [{active, false}]), 116     client_message("connect to ~s:~w ok.", [Host, Port]), 117     server_verify_message(recv_response(Sock), 220), 118     send_command(Sock, "USER " ++ User), 119     server_verify_message(recv_response(Sock), 331), 120     send_command(Sock, "PASS " ++ Pass), 121     server_verify_message(recv_response(Sock), 230), 122     send_command(Sock, "CWD " ++ Path), 123     server_verify_message(recv_response(Sock), 250), 124     send_command(Sock, "TYPE I"), 125     server_verify_message(recv_response(Sock), 200), 126     send_command(Sock, "PASV"), 127     {_, Msg} = recv_response(Sock), 128     server_message(Msg, ""), 129     {Addr, NewPort} = parse_pasv(Msg), 130      131     DataPid = spawn(ftp_down, get_data, [Addr, NewPort, LocalPath ++ File, self()]), 132      133     send_command(Sock, "RETR " ++ File), 134     % 150 Opening BINARY mode data connection for   150 File status okay; about to open data connection. 135     % 125 Downloading in BINARY file  125 Data connection already open; transfer starting. 136     % 550 Failed to open file 137     {Num, Text} = recv_response(Sock), 138     V = (Num == 150) or (Num == 125), 139     if 140         V -> 141             server_message("~s", [Text]), 142             DataPid ! start_transfer, 143             server_verify_message(recv_response(Sock), 226), 144             DataPid ! transfer_complete, 145             receive 146                 bye -> 147                     ok 148             end; 149         true -> 150             if Num == 550 -> 151                 server_message("~w", Text); 152             true -> 153                 ok 154             end 155     end, 156      157     gen_tcp:close(Sock). 

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.