erlang初步,从倾国倾城开始学习erlang,第一篇-基本语法

11 篇文章 0 订阅
9 篇文章 1 订阅

昨晚更新的倾国倾城不知怎么没了,没办法,这篇文章要重写,说道erlang的架设非常简单,这里就不多写了,从网上下载erlang64位,python2.7安装到电脑上,然后设置环境变量

,然后在网上下载倾国倾城的客户端和服务器端,进入服务器端文件夹,点击startup.bat


修改客户端连接的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>1</key>
	<dict>
		<key>idx</key>
		<string>1</string>
		<key>name</key>
		<string>一区</string>
		<key>servers</key>
		<dict>
			<key>100</key>
			<dict>
				<key>idx</key>
				<string>100</string>
				<key>name</key>
				<string>简雨测试服</string>
				<key>ip</key>
				<string>127.0.0.1</string>
			</dict>
			<key>300</key>
			<dict>
				<key>idx</key>
				<string>300</string>
				<key>name</key>
				<string>测试服1</string>
				<key>ip</key>
				<string>127.0.0.1</string>
			</dict>
			<key>400</key>
			<dict>
				<key>idx</key>
				<string>400</string>
				<key>name</key>
				<string>测试服2</string>
				<key>ip</key>
				<string>127.0.0.1</string>
			</dict>
		</dict>
	</dict>
	<key>2</key>
	<dict>
		<key>idx</key>
		<string>2</string>
		<key>name</key>
		<string>二区</string>
		<key>servers</key>
		<dict>
			<key>200</key>
			<dict>
				<key>idx</key>
				<string>200</string>
				<key>name</key>
				<string>9秒测试服</string>
				<key>ip</key>
				<string>127.0.0.1</string>
			</dict>
			<key>500</key>
			<dict>
				<key>idx</key>
				<string>500</string>
				<key>name</key>
				<string>测试服3</string>
				<key>ip</key>
				<string>127.0.0.1</string>
			</dict>
		</dict>
	</dict>
</dict>
</plist>
有vs2010打开客户端,

跟正常的cocos2dx编译方法没有区别,






这个游戏的架设方法跟kbe架设难度没有可比性,不过erlang在国内受欢迎程度可不是一般的,自从神仙道横行国内页游市场之后,越来越多的公司注意erlang服务器了,倾国倾城这个游戏虽然客户端是纯c++,不能像lua一样进行热更新,不过贵在写的很完整,值得一看,另外服务器端是一个完整网友的脚本系统,对学习erlang有相当大的帮助,好了就到这。

这里先占个位置,昨晚的文章不知怎么有更出来了,所以在后面补一段erlang的基本语法吧

一、Erlang语法:变量、模式匹配
--------------------------------------
1.elr命令:工具栏toolbar:start().
2.%。。。注释
3.变量首字母大写,单一赋值
4.模式匹配
5.原子:hello, 'an atom with'
6.元组tuple:元组嵌套{person,{a,1},{b,2}}
             提取元组字段值Point = {point, 10, 45}  {point, X, Y} = Point
7.列表list:  定义列表ThingsToBuy1 = [{oranges,4}, {newspaper,1}|{ThingsToBuy}]
             提取元素[Buy1|ThingsToBuy2] = ThingsToBuy1.
8.字符串:"hello"
9.q()退出
10.f()释放变量


二、Erlang语法:函数(面向函数编程:函数可以作为参数,也可以作为返回值,可以使用列表解析、断言、case/if、二进制、比特位、进制、ASCII码)
--------------------------------------
1.函数
  编译:c(geometry)
  运行:geometry:area({rectangle, 10, 5}).
2.匿名函数:Double = fun(X) -> 2*X end.
         Double(2).
  Hypot = fun(X, Y) -> math:sqrt(X*X+Y*Y) end.
  TempConvert = fun({c,C}) -> {f, 32+C*9/5};
                   ({f,F}) -> {c, (F-32)*5/9}
     end.
3.fun作为函数参数
  映射:lists:map(Double, [1,2,3,4]).
      返回[2,4,6,8].
  过滤:lists:filter(Even, [1,2,3,4]).
      Even = fun(X) -> (X rem 2) =:= 0 end.
4.返回fun的函数
  Fruit = [apple,pear,orange].
  MakeTest = fun(L) -> (fun(X) -> lists:member(X,L) end) end.
  IsFruit = MakeTest(Fruit).
  即:IsFruit = fun(X) -> lists:member(X,[apple,pear,orange]) end.
5.循环
  for(Max,Max,F) -> [F(Max)];
  for(I,Max,F)   -> [F(I)|for(I+1,Max,F)]
6.列表解析
  [2*X || X <- L].
  定义:Buy = [{oranges,4},{newspaper,1},{apples,10},{pears,6},{milk,3}].
  乘积:[shop:cost(A)*B || {A,B} <- Buy]
  求和:libs:sum([shop:cost(A)*B || {A,B} <- Buy]).
  (1)快速排序:L=[12,6,2,13,2,8,9,10]. qsort(L).
  (2)毕达哥拉斯三元组:libs:pythag(16).
  (3)变位词:libs:perms("123").
            ["123","132","213","231","312","321"]
7.算术表达式
8.断言:
  max(X,Y) when X > Y -> X;
  max(X,Y) -> Y.
  断言函数:
  f(X,Y) when is_integer(X), X > Y, Y < 6 -> X;
9.记录:record
10.case表达式:
  filter(P, [P|T]) ->
      case P(H) of
          true -> [H|filter(P,T}];
   false ->filter(P,T)
       end;
  filter(P, []) -> [].
11.if表达式:
12.内建函数BIF
  元组转换为列表:tuple_to_list({12,cat,"Hello"}).
  系统时间:time()
13.二进制数据:<<5,10,20>>,<<"hello">>
  操纵:list_to_binary()
        term_to_binary()
 binary_to_term()
 size()
14.比特语法:<>
  file:read_file("")
15.动态调用:apply(libs, sum, [1,2,3,4]).
16.模块定义:-module(modname).
  引入:-import(modname, [fun/1]). 可以不写模块名直接引用函数名
  导出:-export([name1/1, name2/2]).
  编译属性:-compile(options).
  模块版本:-vsn(Version).
  用户定义属性:-SomeTag(Value).
  输出属性:attr:module_info().
            attr:module_info(attributes).
  引用函数:fun Mod:RemoteFunc/Arity
  包含文件:-include(Filename).
           -include_lib(Name).
  列表操作符:[1,2,3]++[4,5,6]
              [1,2,3]--[2,3]
  进制:K#123
  $语法:$C 表示ASCII
  字典:erase(), put(x, 20),get(x), erase(x)
  短路表达式:Epr1 orelse Epr2.  Epr1 andalse Epr2.


三、Erlang语法:编译运行
--------------------------------------
1.退出:halt().导致数据库要恢复  q().安全退出,等价于init:stop().
2.取得加载路径:code:get_path().
  取得主目录:init:get_argument(home).
3.外部运行:D:/erl>erl.exe -noshell -s hello start -s init stop
4.帮助:help().


四、Erlang语法:并发(进程类似于人:通过消息进行沟通,也可以广播;没有共享内存,因此不需要锁;某一个死掉,会通知链接进程)
--------------------------------------
1.创建进程:Pid = spawn(Fun)
  spawn(Mod, FuncName, Args).
2.发送消息:Pid!Message
  群发消息:Pid1!Pid2!Pid3...!Pidn!Message
  接收消息:receive ... end.
  例如:Pid = spawn(fun area_server0:loop/0).
        Pid!{rectangle, 6, 10}.
3.自身ID:self().
  Pid!{self(), Message}.
  例如:Pid = spawn(fun area_server1:loop/0).
       area_server1:rpc(Pid, {rectangle, 6, 10}).
4.设置进程数:D:/erl>erl +P 500000
  测试启动时间:process:max(400000).
5.注册进程:register(AnAtom, Pid).  注册进程别名
            unregister(AnAtom).   溢出注册进程
     whereis(AnAtom) -> Pid | undefined 判断是否注册
     registered() -> [AnAtom::atom()] 取得所有注册进程
  例如注册时钟:clock:start(5000, fun() -> io:format("TICK ~p~n", [erlang:now()]) end).
      停止时钟:clock:stop().
6.并发错误:链接进程


五、Erlang语法:分布式
--------------------------------------
1.单节点测试
启动服务器:kvs.start().
存储: kvs:store({location, joe}, "Stockholm").
 kvs:store(weather, raining).
查找: kvs:lookup(weather).
 kvs:lookup({location, joe}).
2.双节点测试
启动服务器节点:
 D:/erl>erl -sname gandalf
 Eshell V5.7  (abort with ^G)
 (gandalf@zhongbingliu)1> kvs:start().
 true
 (gandalf@zhongbingliu)2>

调用者节点:
 D:/erl>erl -sname bilbo
 Eshell V5.7  (abort with ^G)
 (bilbo@zhongbingliu)1> rpc:call(gandalf@zhongbingliu, kvs, store, [weather, fine]).
 true
 (bilbo@zhongbingliu)2> rpc:call(gandalf@zhongbingliu, kvs, lookup, [weather]).
 {ok,fine}
3.客户机和服务器位于同一局域网的不同机器上
4.客户机和服务器位于因特网的不同机器上:确保4396端口通信正常,epmd会使用这个端口


六、Erlang语法:文件
--------------------------------------
1.读取文件:file:consult("data1.data").
2.读取一项:{ok, S} = file:open("data1.data", read). //打开
    io:read(S, ''). //读取一项
    io:get_line(S, ''). //读取一行
    file:close(S). //关闭
3.查找代码库位置:code:which(file).
    d:/erl5.7/lib/kernel-2.13/ebin/file.beam
4.读取二进制数据:
    file:read_file("data1.data"). //全部读到内存
    {ok, S} = file:open("data1.data", [read,binary,raw]). //打开
    file:pread(S, 22, 46). //随机读取
5.查找文件:lib_find:files
6.写入文件:{ok, S} = file:open("data2.data", write). //打开
    io:format(S, "~s~n", ["Hello readers"]). //写入
    file:close(S). //关闭
7.随机写入:
    {ok, S} = file:open("data3.data", [raw,write,binary]). //打开
    file:pwrite(S, 10, <<"new">>). //随机写入
8.目录操作:file:list_dir("/"). //文件列表
     file:make_dir("abc"). //创建目录
     file:del_dir("abc"). //删除目录
9.文件属性:file:read_file_info("data1.data").
10.文件操作:file:copy("data1,data", "/"). //拷贝
            file:delete("data1"). //删除


七、Erlang语法:套接字
--------------------------------------
1.Socket连接www:socket:nano_get_url().
2.启动服务器:server:start_nano_server().
3.编写客户端:client:nano_client_eval("list_to_tuple([2+3*4,10+20])").
主动型:非阻塞 服务器接收消息的速度必须快于客户端发送的速度,否则服务器会因为消息缓冲区塞满被消息淹没
被动型:阻塞
混合型:半阻塞


八、Erlang语法:数据库
--------------------------------------
1.ETS是内存存储,速度快
2.DETS是磁盘存储,可备份
3.创建表:ets:new
 dets:open_file
4.插入:insert(table, X)
5.查找:lookup(table, Key)
6.释放:dets:close(tableid) etd:delete(tableid)
7.Mnesia数据库:
  创建表:-record...
  选取所有数据:do(qlc())...
  选取部分列:
  按条件选取:
  关连查询:
  增加数据:mnesia:write()
  删除数据:mnesia:delete()
  事务管理:mnesia:transaction(F)
  取消事务:mnesia:abort()
  启动表查看器:tv:start().


九、Erlang语法:OTP
--------------------------------------
1.支持事务:使用异常捕捉进行回滚
2.支持热代码替换
3.错误日志
4.警报管理
5.应用程序监视器:appmon:start().


十、Erlang语法:JInterface
--------------------------------------
OptNode 节点,监听端口 能够启动多个服务节点,如gurka@sallad.com
Epmd 
OptMbox 默认启动一个邮箱 收发邮件
Link 监控远程是否断掉



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Erlang中,我们可以使用`gen_tcp`模块来实现TCP客户端。下面是一个简单的例子,展示如何使用`gen_tcp`模块来连接到一个服务端: ```erlang -module(tcp_client). -export([start/1]). start(Host) -> {ok, Socket} = gen_tcp:connect(Host, 80, [binary, {packet, 0}]), gen_tcp:send(Socket, "GET / HTTP/1.0\r\n\r\n"), receive_data(Socket), gen_tcp:close(Socket). receive_data(Socket) -> case gen_tcp:recv(Socket, 0) of {ok, Data} -> io:format("~s", [Data]), receive_data(Socket); {error, closed} -> ok end. ``` 在上面的例子中,`gen_tcp:connect`函数用于连接到指定的服务端。`Host`参数是服务端的IP地址或域名,`80`是服务端的端口号。`[binary, {packet, 0}]`选项说明我们要传输二进制数据,且数据包不需要打包。 一旦连接建立成功,我们就可以使用`gen_tcp:send`函数向服务端发送数据了。在这个例子中,我们发送了一个HTTP GET请求。接着,我们调用了`receive_data`函数来接收服务端返回的数据。`gen_tcp:recv`函数用于接收服务端发送的数据。`0`参数表示接收的数据包没有大小限制。如果接收到数据,我们就打印出来,并继续调用`receive_data`函数来接收更多的数据。如果服务端关闭了连接,`gen_tcp:recv`函数会返回错误信息`{error, closed}`,我们就可以关闭连接了。 在使用`gen_tcp`模块时,我们需要注意以下几点: - 为了避免阻塞,在发送和接收数据时,我们可以使用`gen_tcp:send/2`和`gen_tcp:recv/2`函数的阻塞模式,即将第二个参数设置为`0`。这样,如果没有数据可发送或接收,函数就会马上返回。 - 如果我们需要发送和接收大量的数据,应该使用`{packet, N}`选项来打包数据。这个选项会将数据分成大小为N的块,并且在每个块前面添加4个字节的头部,用于表示这个块的大小。这样可以避免粘包问题。 - 在发送和接收数据时,我们应该按照服务端和客户端的协议来组织数据包。如果协议有变化,我们也需要修改代码来适应新的协议。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值