I'm just learning Erlang, so please bear with me. I've read Erlang & OTP in Action, and am currently reading through Joe Armstrong's book right now. That said, I am currently a Sr. Flash developer, so my background is still a little fresh concerning programming concepts that I'm sure most of you are already well-versed in.
I want to build a server for mobile & flash multiplayer games that utilizes a secure TCP connection to authenticate people, but then opens a UDP port to send/receive information. I decided to post here because all I need is a little kick in the right direction. I figured my first goal would be to set up a simple server that is able to send/receive from a very simple client, written in Objective-C. This would allow the user to drag a ball around the screen, essentially sending the coordinates of the user's input to the server, it checks with the basic mechanics, and sends back so many frames per second the location of an on-screen ball. My goal is to incorporate simple physics, but I really want to start small and get off on the right foot. Would someone please walk me through doing this the proper way, using OTP standards? I want to make sure that I don't create any bad habits, and so far I have understood the books I've read. Reading and creating a fully working example is two completely different things though. Thanks so much in advance! |
http://erlagner.org/
There's a few projects in there which might be of help to you. If you search for "gen_tcp" you'll get some good information as well.
Also, http://learnyousomeerlang.com/ is a very good resource as well.
Gluck! -mox On Tue, Apr 12, 2011 at 7:22 PM, Mode7James <[hidden email]> wrote: I'm just learning Erlang, so please bear with me. I've read Erlang & OTP in _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
Thanks Mike! I discovered learnyousomeerlang.com today at work and have been reading through it. That TCP tutorial is also good. I guess it's just a bit overwhelming, trying to put it all together. I read through the TCP tutorial by 20bits tonight and will try to get it working tomorrow after work.
Please bear with me - these are all questions I've had while reading and researching Erlang in my spare time the last couple months. 1) gen_server is a behavior. It's a little confusing that gen_udp and gen_tcp are both modules, but use the same naming conventions. I've seen quite a few documents on how one uses "gen_server" as a behavior - is there any that actually show what the text file looks like? Can I create my own behaviors? I come from a flash background (Java) so I'm very familiar with interfaces. Can one module implement multiple behaviors, or is it only one-to-one direct relationship? Is there somewhere that I can see the complete master list of built-in OTP behaviors and what they do? 2) In the 20bits article, how is the port number generated? Are port numbers unique to an application, or are there different port numbers for different protocols? Is this secure? How do Erlang services deal with DDOS attacks? Are there any tried-and-true methods that are used? 3) Can someone log in via TCP connection, authenticate credentials upgrading to SSL, and then also open a UDP connection for the gameplay mechanics? 4) I've read that distributed Erlang is using "all or nothing" security, ie nodes with access can essentially do whatever they want. Is there a way to keep a service running on a dedicated server, and remotely hotswap code via my macbook? Any examples of this being done? Thanks for putting up with my questions. :) |
2011/4/13, Mode7James <[hidden email]>:
[...] > 1) gen_server is a behavior. It's a little confusing that gen_udp and > gen_tcp are both modules, but use the same naming conventions. I've seen > quite a few documents on how one uses "gen_server" as a behavior - is there > any that actually show what the text file looks like? Very very simple example: -module(s). -behaviour(gen_server). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, start/1]). init(Args) -> {ok, Args}. handle_call(stop, _, _) -> {stop, stopped, empty}; handle_call(Request, _From, State) -> io:format("~p ~n", [Request]), timer:sleep(10000), io:format("slept ~p ~n", [Request]), {reply, Request, State}. handle_cast(_Request, State) -> {noreply, State}. handle_info(Request, State) -> io:format("info: ~p ~n", [Request]), {noreply, State}. terminate(_, _) -> ok. code_change(_, _, _) -> {ok, nostate}. start(Args) -> gen_server:start(s, ?MODULE, Args, []). > Can I create my own > behaviors? Yes, just export a behaviour_info/1 function from your module which returns the expected functions: behaviour_info(callbacks) -> [{foo, 1}, {bar, 2}]. > I come from a flash background (Java) so I'm very familiar with > interfaces. Can one module implement multiple behaviors, or is it only > one-to-one direct relationship? You can implement multiple behaviours. > Is there somewhere that I can see the > complete master list of built-in OTP behaviors and what they do? Well, the generally useful are gen_server, gen_fsm, supervisor and maybe gen_event, they are documented. There are some application-specific behaviours like snmpa_discovery_handler or ssh_sftpd_file_api. They are documented with the applications (mostly). [...] > 3) Can someone log in via TCP connection, authenticate credentials upgrading > to SSL, As far as I know, this is possible. > and then also open a UDP connection for the gameplay mechanics? UDP is stateless, so I'm not quite sure what do you mean by "UDP connection". Of course, you can send UDP packets whenever you want, but you have to devise a clever authentication method that makes e.g. replay attacks impossible. _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
On 13 April 2011 12:57, Attila Rajmund Nohl <[hidden email]> wrote: 2011/4/13, Mode7James <[hidden email]>: http://www.erlang.org/doc/man/ssl.html#connect-3 cheers Chandru _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
In reply to this post by Mode7James
On Apr 13, 2011, at 3:17 AM, Mode7James wrote: > 1) gen_server is a behavior. It's a little confusing that gen_udp and > gen_tcp are both modules, but use the same naming conventions. I've seen > quite a few documents on how one uses "gen_server" as a behavior - is there > any that actually show what the text file looks like? Can I create my own > behaviors? I come from a flash background (Java) so I'm very familiar with > interfaces. Can one module implement multiple behaviors, or is it only > one-to-one direct relationship? Is there somewhere that I can see the > complete master list of built-in OTP behaviors and what they do? Think of behaviours as interfaces, although they are not strictly enforced. You can define your own, here's an example: http://www.trapexit.org/Defining_Your_Own_Behaviour gen_udp and gen_tcp (and gen_sctp) are not, strictly speaking, behaviours. I've always wondered why they are named that way. The big 5 are gen_server, gen_fsm, gen_event, supervisor and application. The vast majority of OTP compliant code that I've seen is built on these five. You can have a module implement multiple behaviours, just be careful about callback clashes > 2) In the 20bits article, how is the port number generated? Are port > numbers unique to an application, or are there different port numbers for > different protocols? Is this secure? How do Erlang services deal with DDOS > attacks? Are there any tried-and-true methods that are used? The 20bits article is pretty good, but I'd recommend using gen_nb_server for building tcp servers. You can find it here: https://github.com/kevsmith/gen_nb_server It is a 3rd party behaviour for building performant, non-blocking tcp servers > 3) Can someone log in via TCP connection, authenticate credentials upgrading > to SSL, and then also open a UDP connection for the gameplay mechanics? Yes, that's probably doable, but you'd have to be more specific as to what exactly want to do. For example, there's not such thing as a "udp connection". You can fire off UDP packets to anywhere, if there's someone listening, they'll get them, otherwise they'll be dropped. Do you want to open one UDP port for each authenticated user or have all of them send data to a single, common UDP port? > 4) I've read that distributed Erlang is using "all or nothing" security, ie > nodes with access can essentially do whatever they want. Is there a way to > keep a service running on a dedicated server, and remotely hotswap code via > my macbook? Any examples of this being done? As long as you have shell access to your remote server, you can certainly do hot updates Mihai _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
As far as I know, behaviours are more than interfaces; they imply that divide between a generic and a specific bit of code, with the generic one being well-behaved and the specific one being relatively unsafe. Moreover, it also implies giving up the control of the flow to the behaviour module, restraining the callback module to specific details.
An Interface is much more generic and only has a meaning in terms of contracts in this particular case. I might be taking a purist approach, but I think the distinction is important. I think behaviours are a rather poor tool to determine an interface itself compared to real contracts that could be enforced by the compiler or Dialyzer. On 2011-04-13, at 09:12 AM, Mihai Balea wrote:
_______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
On Apr 13, 2011, at 9:17 AM, Frédéric Trottier-Hébert wrote: > As far as I know, behaviours are more than interfaces; they imply that divide between a generic and a specific bit of code, with the generic one being well-behaved and the specific one being relatively unsafe. Moreover, it also implies giving up the control of the flow to the behaviour module, restraining the callback module to specific details. > > An Interface is much more generic and only has a meaning in terms of contracts in this particular case. > > I might be taking a purist approach, but I think the distinction is important. I think behaviours are a rather poor tool to determine an interface itself compared to real contracts that could be enforced by the compiler or Dialyzer. True, but I wouldn't go that far with someone who's just starting to learn about this stuff... Mihai _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
In reply to this post by Mode7James
Also, keep in mind that on mobile devices you can have a very severe lag when the user is not on wi-fi so simply sending the location of the on-screen ball will cause sync issues, specially if it's a multiplayer game.
Like you said, they'll be a fair amount of physics involved. Even though it is best practice to use some of the gen_* modules, when I was starting (still a bit of a noob) I decided to make my own tcp and state machines using the erlang basics. Although I haven't done this yet, from a bit of research it really shouldn't be a big issue upgrading that basic erlang code to say something like gen_tcp. At the same time, you get a better understanding of the basics.
At this level, you can prototype your architecture a little more freely, like adding authentication at the socket/tcp level. Sleeping before disconnecting users, switching to ssl, send udp packets at certain events, etc.
On Tue, Apr 12, 2011 at 7:22 PM, Mode7James <[hidden email]> wrote: I'm just learning Erlang, so please bear with me. I've read Erlang & OTP in My goal is to incorporate simple physics, but I really want to start small -- ~ Jeremiah:9:23-24 Android 2D MMORPG: http://solrpg.com/, http://www.youtube.com/user/revoltingx _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
In reply to this post by Mihai Balea
Hey thanks guys, these are great responses! After reading and researching this language a couple months on my own, it's nice to finally meet a few people that know Erlang and are nice enough to answer my questions! I half expected a bunch of "google it" answers. :)
Yes, I agree and completely understand "re-learning" what I have already learned. Flash (Java) is completely different from Erlang, however learning Erlang it's really amazing what you can do with it with just a few lines of code. Pattern-matching is the shit, I'm surprised it isn't used more for search algorithms. Regular Expressions are a pain compared to Erlang! And don't get me started on the bit syntax. There's quite a bit that I still need to learn about servers in general, ie how they actually work. It wasn't until a few days ago that I learned that an HTTP server essentially is a TCP server, receiving requests, and then sending the data over the TCP connection. :) I will need UDP so that I can send fast unreliable packets for user input and the state of the game. A couple people have asked what my goal is: To start, my goal is to create a server that allows secure authentication from a client written in another language, and then my erlang server receives UDP packets which have the x, y, radius coordinates of a "ball" on the client, written in Objective-C. Essentially my first test will be the ability to open up the program on my iPad, log in, and then be able to move a red 2d circle around the screen, simply sending the position coordinates via unreliable UDP, and receiving the current state of all on screen objects on an interval. It's pretty straightforward from there - adding limited 2d physics, which I would like to implement as a linked-in driver, and the ability to add users with a load bearing algorithm. Speaking of load bearing, is there a way for Erlang to read the cpu load of a machine or machine that a node is run on? Also, regarding linked-in drivers: I hear that if they crash, then it brings the entire VM down. Is this just in case there is a bad piece of code? If they are this unstable, then why are they used in production environments? For something like an MMO server, I'll want extremely low latency between the Erlang side and my math & physics side - but I also need it to be stable so if something messes up or crashes, it doesn't bring the entire system down. Thanks again - I just want to make sure I'm developing proper habits, and building this thing the right way ;) |
In reply to this post by Miguel Morales
Thanks Miguel - you touched on a couple of my questions as I was writing them!
Yes - for 3G the latency is pretty bad. Even Wi-Fi I want to build for the lowest common denominator, and then it can be tweaked for each project. There will be a fair amount of predictiveness in the client engine to account for the lag, which is something we have to do for flash multiplayer games as well. Also, flash is TCP only, so there's an added side effect of all network traffic stopping on the flash end until the packets are confirmed delivered. |
In reply to this post by Mode7James
On Apr 13, 2011, at 12:26 PM, Mode7James wrote:
They're not inherently unstable, its just that you're running (possibly buggy) native code inside your VM I would suggest you implement your logic in Erlang first, and only if it turns out you need better performance, think of native code. In many cases you won't need to. Also, in many cases tweaking the algorithm will bring you a whole lot more performance gains than going native. Mihai _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
I read through this thread which sheds a little light on the subject: http://erlang.2086793.n4.nabble.com/NIF-vs-Linked-in-Drivers-td2103764.html
Perhaps I'm not understanding this concept correctly. Are you saying that a linked-in driver is stable as long as there are no bugs in the native library, ie if the native library has been tested, then it should be fine and run with no issues? Or, if say my physics library gets a billion things all at once and decides to implode, so it crashes - does the whole computer running this process crash as well? Is there a way to segment it so that it doesn't crash the whole system? By "beam process" does it crash just the process that is currently running the linked-in driver or the entire system? From what I thought, it would crash the entire system, ie the machine that is running the Virtual Machine. Is there a better way to keep latency extremely low, sending and receiving millions of variables on the same machine many times per second? I'm thinking of it like a box - the Physics box gets the current state & velocities, figures out the new state, and returns the state back to Erlang, which then takes things from there and delivers them to the appropriate parties. I understand and will be implementing things in Erlang at the start for testing purposes, however I want to make my physics system modular and use a library that can be installed both on the server and on the client, so what is ultimately used for the various math-intensive things will need to be written in a language like C++. I've been planing on using Box2d and Bullet, which can both be implemented on iOS, Android, Mac & PC, as well as server-side. Am I approaching this correctly? |
Hi James,
"Let it crash" is the Erlang way of doing things, but it does NOT mean, let the VM crash, but Erlang processes. The VM is the saint cow in this context that absolutely must not crash. > Are you saying that a > linked-in driver is stable as long as there are no bugs in the native > library, ie if the native library has been tested, then it should be fine > and run with no issues? You mean library = driver I guess. Yes, when it is as stable as Erlang proper. > Or, if say my physics library gets a billion things > all at once and decides to implode, so it crashes - does the whole computer > running this process crash as well? No but the Erlang VM, if it's linked-in. Which is something you could otherwise almost completely rely upon to keep running and keep restarting and redoing whatever the uncompleted tasks had been when an Erlang-process crashed (which, again, is a different level of crashing). > Is there a better way to keep latency extremely low, sending and receiving > millions of variables on the same machine many times per second? It is. Not quite as fast as a function call but close. > I'm > thinking of it like a box - the Physics box gets the current state & > velocities, figures out the new state, and returns the state back to Erlang, > which then takes things from there and delivers them to the appropriate > parties. > > I understand and will be implementing things in Erlang at the start for > testing purposes, however I want to make my physics system modular and use a > library that can be installed both on the server and on the client, so what > is ultimately used for the various math-intensive things will need to be > written in a language like C++. I've been planing on using Box2d and > Bullet, which can both be implemented on iOS, Android, Mac & PC, as well as > server-side. Am I approaching this correctly? > But in general it sounds very much like what you want is NOT a linked-in driver but a port to a separate Erlang VM, that resides on the same machine. I think this is an example of how you'd want to do it: http://gitorious.org/erlua/erlua/blobs/2fa39a954df8a6a5d7318dac7dc5728a830dab77/README Just you wouldn't embed Lua but your physics. Best, Henning _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
This is exactly they type of example I'm looking for, thanks Henning! And I've been thinking I should embed a scripting language like Lua for developers extending things without modifying underlying code, so this is a really great find, thanks.
So, just so I understand you correctly on the whole linked-in vs port driver thing: Each computer has one instance of the Erlang VM running. Each VM can have many processes. Using a linked-in driver essentially treats that C module as an extension of the Erlang VM itself, so if it crashes, so do all of the processes that are running in that VM on the individual machine. Does the VM restart automagically, or does it require a manual restart? Say it crashes at 3a.m. does it require someone to come out and restart it and start all of the nodes? A port driver, on the other hand, is treated as a separate node. If it crashes, it is contained within that node. It is slightly slower than a linked-in driver though. Is it fast enough to implement many messages per second back & forth? By saying it's not quite as fast as a function call I'm assuming you mean a linked-in driver call, right? Essentially a port driver is probably best for implementing hardcore math many times per second, right? This is really cool by the way. All of these questions I've had for quite a while, searching Google for examples & such. Thanks! -James |
Welcome!
> This is exactly they type of example I'm looking for, thanks Henning! And > I've been thinking I should embed a scripting language like Lua for > developers extending things without modifying underlying code, so this is a > really great find, thanks. > Be sure to check out other projects re Lua. This was really referred to as an example of architecture. > Each computer has one instance of the Erlang VM running. You can have more, in fact, 2 might make sense and that's what I think might be what you want. > Each VM can have > many processes. Using a linked-in driver essentially treats that C module > as an extension of the Erlang VM itself, so if it crashes, so do all of the > processes that are running in that VM on the individual machine. Right. > Does the > VM restart automagically, or does it require a manual restart? Erlang is made for the VM never to crash and it has an elaborate structure on how processes inside the VM restart each other and supervise each other. That architecture can span multiple 'nodes'. But when crashing, dying, exiting is talked about, in general you want it all to happen 'gracefully' and not have to restart the entire VM. BUT you could decide to have your C library linked-in to one Erlang VM, with very thin Erlang code on top, that talks to another VM (node) and of that first one you make sure comes up automatically if the whole VM crashes, e.g. due to the C stuff, while the second is your main Erlang node. > A port driver, on the other hand, is treated as a separate node. If it > crashes, it is contained within that node. It is slightly slower than a > linked-in driver though. Is it fast enough to implement many messages per > second back & forth? Absolutely. > By saying it's not quite as fast as a function call > I'm assuming you mean a linked-in driver call, right? Yes. But also in Erlang proper, sending messages is a tad slower than function calls. > Essentially a port > driver is probably best for implementing hardcore math many times per > second, right? > Many times per second would be "low frequency" and so, especially if you must realistically expect crashes, yes. Henning _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
Depending on the problem, but if you want more raw math power,
physics can be calculated with OpenCL, and by using that you don't have to write a driver (or nif lib) yourself. But as always write it in erlang first then go the driver/OpenCL route, and you have a nice debugged reference implementation as well. /Dan On Wed, Apr 13, 2011 at 9:06 PM, H. Diedrich <[hidden email]> wrote: > Welcome! >> >> This is exactly they type of example I'm looking for, thanks Henning! And >> I've been thinking I should embed a scripting language like Lua for >> developers extending things without modifying underlying code, so this is >> a >> really great find, thanks. >> > > Be sure to check out other projects re Lua. This was really referred to as > an example of architecture. >> >> Each computer has one instance of the Erlang VM running. > > You can have more, in fact, 2 might make sense and that's what I think might > be what you want. >> >> Each VM can have >> many processes. Using a linked-in driver essentially treats that C module >> as an extension of the Erlang VM itself, so if it crashes, so do all of >> the >> processes that are running in that VM on the individual machine. > > Right. >> >> Does the >> VM restart automagically, or does it require a manual restart? > > Erlang is made for the VM never to crash and it has an elaborate structure > on how processes inside the VM restart each other and supervise each other. > That architecture can span multiple 'nodes'. But when crashing, dying, > exiting is talked about, in general you want it all to happen 'gracefully' > and not have to restart the entire VM. > > BUT you could decide to have your C library linked-in to one Erlang VM, with > very thin Erlang code on top, that talks to another VM (node) and of that > first one you make sure comes up automatically if the whole VM crashes, e.g. > due to the C stuff, while the second is your main Erlang node. >> >> A port driver, on the other hand, is treated as a separate node. If it >> crashes, it is contained within that node. It is slightly slower than a >> linked-in driver though. Is it fast enough to implement many messages per >> second back & forth? > > Absolutely. >> >> By saying it's not quite as fast as a function call >> I'm assuming you mean a linked-in driver call, right? > > Yes. But also in Erlang proper, sending messages is a tad slower than > function calls. >> >> Essentially a port >> driver is probably best for implementing hardcore math many times per >> second, right? >> > > Many times per second would be "low frequency" and so, especially if you > must realistically expect crashes, yes. > > Henning > _______________________________________________ > erlang-questions mailing list > [hidden email] > http://erlang.org/mailman/listinfo/erlang-questions > erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
In reply to this post by Henning Diedrich-2
I'm starting to get it now.
Essentially creating a thin wrapper VM for a linked-in library is pretty much the same thing as a port driver, right? It basically creates a new node, so functions are called by passing messages, which then we go back to messages vs function calls. Why re-create the wheel? Is there a speed difference between the two do you think, or should I stick with a port driver? If my physics node, using a port driver, crashes, is there an automated way to bring it back and restart it without manually restarting it? If not through Erlang itself, has anyone developed an underlying C-based application that runs as an overall supervisor? Keeping track of VM's that crash, and restarting as necessary? |
In reply to this post by Dan Gudmundsson-2
Is OpenCL available on a server? I won't be running Erlang in the client, but rather the server-side only. This is something I never thought of. |
In reply to this post by Mode7James
1. Is there an idiomatic way to use dependency injection in erlang?
Most of my use of Spring DI has been to facilitate injection of test classes into a stack for functional testing. Is this sort of thing done in erlang? 2. How about AOP style join-points for before and after execution around a method? As an example, wouldn't it be cool to dynamically enable debug or trace level logging for an application when a certain error threshold is reached? Then, when the system returns to a normal state, the error logging could be turned back down... I think I might start doing this in the Java stacks I'm currently working with (log4j). 3. Is there a way to intercept messages to a process? This is the real question... Say a process dies unexpectedly and OTP restarts it... it would be cool to be able to dynamically proxy messages to a process that has exceeded some error threshold. The proxy could log them, or perform more intensive error analysis... Then, once the system is back in a normal state, the proxy could be removed from the message loop chain. -Todd _______________________________________________ erlang-questions mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-questions |
Free forum by Nabble | Edit this page |