分享

Erlang实现的一个Web服务器代码实例

 新用户3488XG6a 2021-11-22

转贴一个简单的Web服务器:

httpd.erl

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

%% httpd.erl - MicroHttpd

-module(httpd).

-author("ninhenry@gmail.com").

-export([start/0,start/1,start/2,process/2]).

-import(regexp,[split/2]).

-define(defPort,8888).

-define(docRoot,"public").

start() -> start(?defPort,?docRoot).

start(Port) -> start(Port,?docRoot). 

start(Port,DocRoot) ->

 case gen_tcp:listen(Port, [binary,{packet, 0},{active, false}]) of

  {ok, LSock} -> server_loop(LSock,DocRoot);

   {error, Reason}  -> exit({Port,Reason})

 end.

%% main server loop - wait for next connection, spawn child to process it

server_loop(LSock,DocRoot) ->

 case gen_tcp:accept(LSock) of

  {ok, Sock} ->

   spawn(?MODULE,process,[Sock,DocRoot]),

   server_loop(LSock,DocRoot);

  {error, Reason} ->

   exit({accept,Reason})

 end.

%% process current connection

process(Sock,DocRoot) ->

 Req = do_recv(Sock),

 {ok,[Cmd|[Name|[Vers|_]]]} = split(Req,"[ \r\n]"),

 FileName = DocRoot ++ Name,

 LogReq = Cmd ++ " " ++ Name ++ " " ++ Vers,

 Resp = case file:read_file(FileName) of

  {ok, Data} ->

   io:format("~p ~p ok~n",[LogReq,FileName]),

   Data;

  {error, Reason} ->

   io:format("~p ~p failed ~p~n",[LogReq,FileName,Reason]),

   error_response(LogReq,file:format_error(Reason))

  end, 

 do_send(Sock,Resp),

 gen_tcp:close(Sock).

%% construct HTML for failure message

error_response(LogReq,Reason) ->

 "<html><head><title>Request Failed</title></head><body>\n" ++

 "<h1>Request Failed</h1>\n" ++ "Your request to " ++ LogReq ++

 " failed due to: " ++ Reason ++ "\n</body></html>\n".

%% send a line of text to the socket

do_send(Sock,Msg) ->

 case gen_tcp:send(Sock, Msg) of

  ok -> ok;

   {error, Reason} -> exit(Reason)

 end.

%% receive data from the socket

do_recv(Sock) ->

 case gen_tcp:recv(Sock, 0) of

  {ok, Bin} -> binary_to_list(Bin);

   {error, closed} -> exit(closed);

   {error, Reason} -> exit(Reason)

 end

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多