学习 Erlang 一周的习作:
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 <2orelse notstring: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 >0andalso 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 after200->
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 after30000->
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>: ~wBytes~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:~wok.", [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 file125 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 ifNum ==550->
151 server_message("~w", Text);
152 true->
153 ok
154 end
155 end,
156
157 gen_tcp:close(Sock).
分享到:
相关推荐
总体而言,编写分布式的Erlang程序是一项既富有挑战性又充满机遇的任务。通过深入了解Erlang的分布式特性,识别并避免潜在的陷阱,开发者可以构建出高效、可靠且易于维护的分布式系统。此外,随着技术的进步和社区的...
在Erlang中,进程间通信(IPC)是通过消息传递来实现的,而`link`机制是这个通信模型中非常重要的一部分。本教程将通过一个名为"bank2"的实例来探讨`link`的功能和影响。 首先,让我们理解什么是进程`link`。在...
【Erlang程序设计(第2版)】是由Erlang之父Joe Armstrong撰写的一本经典著作,专注于介绍Erlang编程语言在并发、分布式和容错系统中的应用。本书适用于初学者和有一定经验的Erlang程序员。作者在书中讨论了如何利用...
本书由Erlang之父Joe Armstrong编写,是毋庸置疑的经典著作。书中兼顾了顺序编程、并发编程和...第2版全新改写,反应了自第1版面世以来Erlang历经的所有变化,添加了大量针对初学者的内容,并在每章后都附上了练习题。
在这个"Erlang入门:构建application练习5(监督树)"中,我们将探讨如何构建一个包含监督树的应用,这是Erlang OTP(开放电信平台)设计模式中的核心部分。 监督树是Erlang OTP设计原则的重要组成部分,它用于管理...
在本教程中,我们将深入探讨如何使用Erlang构建一个名为"Application"的基本应用程序,这在Erlang生态系统中是一个关键的概念。 在Erlang中,"Application"是一个组织代码的机制,它提供了模块之间的依赖管理和启动...
本项目提供了一个使用Erlang编写的聊天室服务器端代码以及Java编写的客户端代码,这为我们深入理解Erlang的并发特性和Java与Erlang的交互提供了实践案例。 一、Erlang聊天室服务器端 1. 并发处理:Erlang的轻量级...
这个压缩包包含了Erlang程序设计的完整目录和源码,是学习和理解Erlang编程的重要资源。 Erlang的并发特性源于其轻量级进程模型,每个进程都有自己的内存空间,进程间通信通过消息传递实现,这种设计降低了并发执行...
凯 Erlang 客户端 :warning: 在制品。 暂时不要使用。...kairos-cassandra 的 ELB 友好保持活动REST API(添加数据点没有计划,在这个客户端的范围内没有充分的理由去做) 自定义响应包装器 删除数据点 删除指标
Erlang八卦客户端这是一个 Erlang 客户端库。安装将此添加到rebar.config文件: {gossiperl_client, ".*", {git, "https://github.com/gossiperl/gossiperl-client-erlang.git", "master"}},运行rebar get-deps ,...
编写分布式的 Erlang 程序:陷阱和对策 硝烟中的Erlang 深入底层: erlang VM基于多核处理器的可伸缩性特征 erlang VM内部数据共享机制 erlang 消息传递机制 文章地址:...
本资源包含了《Erlang程序设计》一书的所有实例代码,旨在帮助读者深入理解Erlang语言的核心特性和实际应用。 **一、函数式编程基础** Erlang作为函数式编程语言,其核心概念包括不可变数据、纯函数和副作用的最小...
在Erlang中,程序被视为一系列相互独立的函数调用,而不是状态改变的过程。这使得代码更易于理解和测试,因为函数没有副作用,数据不可变。 2. **并发处理** Erlang的并发机制基于轻量级进程(Lightweight ...
1. **进程**:在Erlang中,进程是非常轻量级的,每个进程都有自己的内存空间,通信通过消息传递实现,这使得并发执行变得简单且高效。 2. **函数式编程**:Erlang鼓励使用纯函数,即函数的结果仅取决于输入,不依赖...
- **HTTPErlang**:可能是指Erlang中的HTTP相关库或工具,强调了这个客户端是用Erlang实现的。 **文件名称列表解析:** “hackney-master”可能是库的源代码仓库的主分支名称,通常在Git版本控制系统中,“master...
通过对这些文件名的分析,我们可以看出这些Erlang程序涵盖了并发处理、进程通信、异常处理、服务器设计、数据处理和测试等多个方面,体现了Erlang在构建分布式系统中的强大功能。学习并理解这些示例,对于深入掌握...
"中文版"的Erlang程序设计书籍对于中文阅读者来说是一个宝贵的资源,它将帮助中国开发者更好地理解和应用这一强大的技术,参与到并发和分布式系统的开发中。结合实战经验,Erlang的理论知识可以转化为实际的工程能力...
erldocker, 面向Erlang的Docker 远程API客户端 erldockererldocker 是一个Erlang应用程序,它实现了 Docker 远程 API v1.4.public 模块包括:docker,docker_container 和 docker_image 。设置要开始