`
ruilin215
  • 浏览: 1147709 次
  • 性别: Icon_minigender_2
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

第一个 Erlang 程序: Ftp 下载客户端

阅读更多
学习 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的分布式特性,识别并避免潜在的陷阱,开发者可以构建出高效、可靠且易于维护的分布式系统。此外,随着技术的进步和社区的...

    Erlang入门:构建application练习4(进程link的作用)

    在Erlang中,进程间通信(IPC)是通过消息传递来实现的,而`link`机制是这个通信模型中非常重要的一部分。本教程将通过一个名为"bank2"的实例来探讨`link`的功能和影响。 首先,让我们理解什么是进程`link`。在...

    Erlang程序设计(第2版)1

    【Erlang程序设计(第2版)】是由Erlang之父Joe Armstrong撰写的一本经典著作,专注于介绍Erlang编程语言在并发、分布式和容错系统中的应用。本书适用于初学者和有一定经验的Erlang程序员。作者在书中讨论了如何利用...

    Erlang程序设计(第二版)及源码

    本书由Erlang之父Joe Armstrong编写,是毋庸置疑的经典著作。书中兼顾了顺序编程、并发编程和...第2版全新改写,反应了自第1版面世以来Erlang历经的所有变化,添加了大量针对初学者的内容,并在每章后都附上了练习题。

    Erlang入门:构建application练习5(监督树)

    在这个"Erlang入门:构建application练习5(监督树)"中,我们将探讨如何构建一个包含监督树的应用,这是Erlang OTP(开放电信平台)设计模式中的核心部分。 监督树是Erlang OTP设计原则的重要组成部分,它用于管理...

    Erlang入门:构建application练习2

    在本教程中,我们将深入探讨如何使用Erlang构建一个名为"Application"的基本应用程序,这在Erlang生态系统中是一个关键的概念。 在Erlang中,"Application"是一个组织代码的机制,它提供了模块之间的依赖管理和启动...

    一个我自己学习Erlang的聊天室服务器及客户端代码

    本项目提供了一个使用Erlang编写的聊天室服务器端代码以及Java编写的客户端代码,这为我们深入理解Erlang的并发特性和Java与Erlang的交互提供了实践案例。 一、Erlang聊天室服务器端 1. 并发处理:Erlang的轻量级...

    Erlang程序设计,包含完整目录和全套源码

    这个压缩包包含了Erlang程序设计的完整目录和源码,是学习和理解Erlang编程的重要资源。 Erlang的并发特性源于其轻量级进程模型,每个进程都有自己的内存空间,进程间通信通过消息传递实现,这种设计降低了并发执行...

    kai:Erlang KairosDB 客户端

    凯 Erlang 客户端 :warning: 在制品。 暂时不要使用。...kairos-cassandra 的 ELB 友好保持活动REST API(添加数据点没有计划,在这个客户端的范围内没有充分的理由去做) 自定义响应包装器 删除数据点 删除指标

    gossiperl-client-erlang:Gossiperl Erlang 客户端库

    Erlang八卦客户端这是一个 Erlang 客户端库。安装将此添加到rebar.config文件: {gossiperl_client, ".*", {git, "https://github.com/gossiperl/gossiperl-client-erlang.git", "master"}},运行rebar get-deps ,...

    erlang文献及资料汇总

    编写分布式的 Erlang 程序:陷阱和对策 硝烟中的Erlang 深入底层: erlang VM基于多核处理器的可伸缩性特征 erlang VM内部数据共享机制 erlang 消息传递机制 文章地址:...

    [Erlang程序设计]源代码

    本资源包含了《Erlang程序设计》一书的所有实例代码,旨在帮助读者深入理解Erlang语言的核心特性和实际应用。 **一、函数式编程基础** Erlang作为函数式编程语言,其核心概念包括不可变数据、纯函数和副作用的最小...

    erlang程序设计与入门

    在Erlang中,程序被视为一系列相互独立的函数调用,而不是状态改变的过程。这使得代码更易于理解和测试,因为函数没有副作用,数据不可变。 2. **并发处理** Erlang的并发机制基于轻量级进程(Lightweight ...

    Erlang程序设计及源代码打包

    1. **进程**:在Erlang中,进程是非常轻量级的,每个进程都有自己的内存空间,通信通过消息传递实现,这使得并发执行变得简单且高效。 2. **函数式编程**:Erlang鼓励使用纯函数,即函数的结果仅取决于输入,不依赖...

    hackney:Erlang中的简单HTTP客户端

    - **HTTPErlang**:可能是指Erlang中的HTTP相关库或工具,强调了这个客户端是用Erlang实现的。 **文件名称列表解析:** “hackney-master”可能是库的源代码仓库的主分支名称,通常在Git版本控制系统中,“master...

    erlang程序设计相关例子程序

    通过对这些文件名的分析,我们可以看出这些Erlang程序涵盖了并发处理、进程通信、异常处理、服务器设计、数据处理和测试等多个方面,体现了Erlang在构建分布式系统中的强大功能。学习并理解这些示例,对于深入掌握...

    Erlang程序设计中文版

    "中文版"的Erlang程序设计书籍对于中文阅读者来说是一个宝贵的资源,它将帮助中国开发者更好地理解和应用这一强大的技术,参与到并发和分布式系统的开发中。结合实战经验,Erlang的理论知识可以转化为实际的工程能力...

    erldocker, 面向Erlang的Docker 远程API客户端.zip

    erldocker, 面向Erlang的Docker 远程API客户端 erldockererldocker 是一个Erlang应用程序,它实现了 Docker 远程 API v1.4.public 模块包括:docker,docker_container 和 docker_image 。设置要开始

Global site tag (gtag.js) - Google Analytics