My favorites | Sign in
Logo
                
Search
for
Updated Apr 08, 2009 by discipleofranok
Labels: Phase-Implementation, Featured, Developer, Servlet
WritingAServlet  
Provides a short tutorial for servlet developers.

Introduction

This document outlines the process for writing an OSP servlet and also provides some hints about how to avoid problems with your servlet.

Create the Servlet

The easiest way to start writing a servlet is to download and modify the echo.sdf servlet for a simple echo server. Lets start by taking a look at that, and then go from there.

<?xml version="1.0"?>
<!DOCTYPE osp-servlet PUBLIC "-//Jacob Torrey//Open Server Platform Servlet//EN" "http://www.openserverplatform.com/osp-servlet.dtd">
<osp-servlet>
  <author>Jacob Ian Torrey</author>
  <name>echo</name>
  <version>0.1</version>
  <proto>tcp</proto>
  <code>
  <init><![CDATA[
  init() ->
    io:format("~p is starting!~n", [?MODULE]).
  ]]></init>
  <server><![CDATA[
  server(Sock) ->
    store(name, "My echo server!"),
    Res = recv(Sock, 0),
    if
	% If the socket is closed then exit
	Res =:= {error, closed} ->
	    exit(normal);
	% Otherwise, reply
	true ->
	    io:format("~p ~p ~n", [erlang:binary_to_list(Res), retrieve(name)]),
	    send(Sock, Res),
	    server(Sock)
    end.
  ]]></server>
  <cleanup><![CDATA[
  cleanup() ->
    io:format("~p is stopping!~n", [?MODULE]).
  ]]></cleanup>
  </code>
</osp-servlet>

Now to break this down line by line:

<?xml version="1.0"?>
<!DOCTYPE osp-servlet PUBLIC "-//Jacob Torrey//Open Server Platform Servlet//EN" "http://www.openserverplatform.com/osp-servlet.dtd">

This is the standard XML header and the OSP servlet DTD. This should be familiar if you've even used XML.

<osp-servlet>
  <author>Jacob Ian Torrey</author>
  <name>echo</name>
  <version>0.1</version>
  <proto>tcp</proto>

This next section opens the main osp-servlet container element and also provides some meta-data for the servlet. The most important element is the name element, which must be all lower-case and contain no spaces or special characters except for a ''. This is the name you will use when starting and stopping your servlet. The proto tag can be either 'tcp' or 'udp' which will determine which protocol the servlet will use.

<code>

This starts the actual OSP code which is broken down into three required sub-elements: init, server, cleanup. Each of these elements need to be marked as CDATA using the <!start tag and ]> end tag.

<init><![CDATA[
  init() ->
    io:format("~p is starting!~n", [?MODULE]).
  ]]></init>

These lines define the init function, which has an arity of 0. In this case, it just prints to the screen that ?MODULE (echo in this case) has been started. The init function is called once during the life time of your server, and should be used for variable initialization, etc... If you don't require any initialization, just make your element:

<init><![CDATA[
   init() ->
      ok.
]]></init>

Next, we look at the main section, the server element.

<server><![CDATA[
  server(Sock) ->
    store(name, "My echo server!"),
    Res = recv(Sock, 0),
    if
        % If the socket is closed then exit
        Res =:= {error, closed} ->
            exit(normal);
        % Otherwise, reply
        true ->
            io:format("~p ~p ~n", [erlang:binary_to_list(Res), retrieve(name)]),
            send(Sock, Res),
            server(Sock)
    end.
  ]]></server>

This code must at least define a function server of arity 1 with the argument being the socket reference. You can free to do what you please here, and also define other internal functions for your use. The above code should be rather straight-forward, but just in case, I'll go over it.

server(Sock) ->

The definition of the main server function

store(name, "My echo server!"),

Stores the application global variable 'name' with the value "My echo server!".

Res = recv(Sock, 0),

Sets the local variable 'Res' to be one line of received input from the socket (0 is the number of bytes to read, which 0 being all).

if
        % If the socket is closed then exit
        Res =:= {error, closed} ->
            exit(normal); % Exit with a normal flag, otherwise there will an an error report generated
        % Otherwise, reply
        true -> % This is a catch-all for if statements
            io:format("~p ~p ~n", [erlang:binary_to_list(Res), retrieve(name)]), % Print out what was received from the user, and the value of the global variable 'name'
            send(Sock, Res), % Send to the reply to the user
            server(Sock) % Loop back up ad nausea
    end. % End the if statement

Now, we close the server element and like the init function, we make a sub-element for the cleanup function which is run after a stop command is given.

<cleanup><![CDATA[
  cleanup() ->
    io:format("~p is stopping!~n", [?MODULE]).
  ]]></cleanup>

That's it, now it's just a matter of closing the XML elements and you're done!

</code>
</osp-servlet>

Sign in to add a comment
Hosted by Google Code