Introduction
This document will provide details on how to build an etch application using csharp.
Sample Etch File
The following is the etch file we will refer to in this document. Lets call this File Example.etch and store it in directory c:\EtchExamples\Example
Using Etch Compiler
Before compiling etch file, please make sure Etch is installed and is present in the path
Command Line
- Before we generate the server code, lets create a directory for server (c:\EtchExamples\Example\server).
- From the command line, use the following command to generate the server side code
- This command will generate the server side code under
c:\EtchExamples\Example\server\etch.examples.example
- The directory name "etch.examples.example" is generated by the compiler. This name corresponds to the module name of the etch file.
- Like we did for server, lets create a directory for client (c:\EtchExamples\Example\client)
- Similarly using the following command to generate the client side code
- This command will generate the client code under
c:\EtchExamples\Example\client\etch.examples.example
Please refer to the Etch Compiler Guide for more details on the various compiler options
Visual Studio Plugin
- If you are using Visual Studio as your IDE, then you can install the Visual Studio Etch Plugin. TODO Make sure the setup.exe for the plugin is a part of etch install...
- Once the plugin has been installed, open Visual Studio and goto Tools->Add-in Manager. Make sure Etch is checked
- Create a new Empty solution add two projects client and server to the solution.
- Copy Example.etch to both client and server project
- Right click on the etch file in the solution explorer and chose server compiler option for server project. Add the generated files to the project by right clicking on the project and choosing Add->Existing Item. Do the exact same thing for client project
Generated Files
Once the etch file has been compiled successfully, either from command line or Visual Studio Plugin, a bunch of files are generated.
This section briefly explains the purpose of each generated file.
Interface Files
Example.cs
ExampleClient.cs
ExampleServer.cs
These three files are the generated interface classes. Service defined constants and types are in Example.cs, as well as direction "both" messages, which are messages which are shared between client and server. ExampleClient.cs and ExampleServer.cs are respectively the messages for just the direction client or server. These Files should not be edited by the user
Remote Files
RemoteExample.cs
RemoteExampleClient.cs
RemoteExampleServer.cs
RemoteExample*.cs are the generated classes which implement the interfaces, with message implementations which encode the message type and arguments for transport to the connection peer and then receive and decode any response. These files should not be edited by the user either
Stub Files
StubExample.cs
StubExampleServer.cs
StubExampleClient.cs
StubExample*.cs are the generated classes which receive messages encoded by RemoteExample*.cs and decode them, calling the appropriate message implementation and then encoding and sending any result. These Files are also not edited by the user
Value Factory File
ValueFactoryExample.cs
ValueFactoryExample.cs is a generated class which contains helper code to serialize service defined types and also the meta data which describes the messages and fields, field types, timeouts, etc. This file is also not edited by the user
Base Files
BaseExample.cs
BaseExampleClient.cs
BaseExampleServer.cs
BaseExample*.cs are generated classes which implement the interfaces, with message implementations which call the delegate. If no delegate is defined i.e. if delegate is null, an UnsupportedOperationException is thrown. These files are also not edited by the user
Impl Files
ImplExampleClient.cs
ImplExampleServer.cs
ImplExample*.cs are the generated sample client and server implementation classes. They extend the generated base classes. These are used by the sample main programs to provide implementations of the client or server messages. Edit these files as you wish to implement your service (overriding the default implementations from the generated base classes or uisng delegates).
Helper File
ExampleHelper.cs
ExampleHelper.cs is a generated class which includes static methods to help construct transports for client and listener. This file should not be edited by the user
Main Files
MainExampleClient.cs
MainExampleListener.cs
MainExample*.cs are the generated sample client and server main programs. They show how to setup a transport and start it and how to create a session. Edit these files as you wish to implement your service, or just copy the code into your own application.
Changes Required to Make the Application Work
Only a few files need to be edited to make the etch application run.
MainExampleListener
As mentioned in the previous section, MainExampleListener is the class where the listener (server) is started. The user needs to edit the URI to point to the location where listener must listen for connection from the client
In the above code snippet, the listener will run at port 4002 on localhost.
When the listener accepts a connection from the client, an server object (ImplExampleServer) is created to service the client request. The code to create the Impl object is auto generated by the compiler.
If a user wishes to, he can pass more parameters to the Impl Object. In the context of our example, we do not need to pass any other arguments, thus we will keep the generated code as is.
In summary, editing the uri is the only change required for our example.
ImplExampleServer
In this class, we will provide implementation of any "both" or "server" directed messages. To get a better understanding of what is meant by "both" and "server" directed message, lets look at snippet of Example.etch
The keyword @Direction(....) is used to specify the direction of the message. @Direction(server) implies that the message is headed towards the server. Both implies that the message can be directed towards the server or client. For more details please refer to the Etch Language Reference Manual.
For our purpose, in ImplExampleServer we will only implement the messages that are directed towards server "@Direction(Server)" or both "@Direction(Both)"
ImplExampleServer extends from BaseExampleServer which provides a default implementation of all messages with direction server or both. Below is a snippet of BaseExampleServer
In ImplExampleServer we can either override method helloServer or use the power of delegate (see example below for how to use delegate)
Notice that method SayHello is assigned to delegate _delegate_helloServer in the constructor.
In summary, ImplExampleServer is where the actual server implementation resides. The user can choose to either override the methods in BaseExampleServer or assign methods to delegates.
MainExampleClient
The uri in MainExampleClient needs to be modified such that it points to location where listener was started. In the context of our example the uri will point to the following
The compiler generates code to setup up the transport layer. It also gets an instance of RemoteExampleServer. The client uses RemoteExampleServer to send messages to server.
In the context of our example, we will call method helloServer on RemoteExampleServer. Following is a code snippet
Thus a user only needs to change the uri and use the RemoteExampleServer instance to invoke messages on the server
ImplExampleClient
MainExampleClient also contains method NewExampleClient, which creates an ImplExampleClient object. This class provides implementation of "both" directed and "client" directed messages. This class is analogous to the ImplExampleServer. The only difference being that ImplExampleServer implemented "server" and "both" directed messages, while ImplExampleClient implements "client" and "both" directed messages.
To see ImplExampleClient at work, we will have to modify ImlExampleServer as well. In ImplExampleServer section, we provided implementation of helloServer method using delegates, lets tweak this a little such that the server replies back client with a howdyClient message.
It is very important to remember that howdyClient is defined as a @oneway message in the Example etch file. Such messages don't wait for a response. They are often referred to as event or "fire and forget" message. If howdyClient was not defined as @oneway, it would have resulted in a deadlock or a timeout exception. This is because client would expect to hear back from helloServer message, while server would be waiting to hear back from howdyClient. Since neither can respond until they hear from the other, they will eventually timeout if a timeout has been defined or just wait indefinitely. However since howdyClient message has been defined as @oneway the server does not have to wait for a response from the client.
In summary, ImplExampleClient is the place where the client implementation resides. The user can chose to override the base implementation provided in BaseExampleClient or assign methods to delegates.
Compile and Run the Application
Using CSC
Please make sure that .NET 2.0 or greater is installed on your system
Building on our example, lets first compile the server files.
- The first step would be to change directory to the server location
(c:\EtchExamples\Example\server\etch.examples.example).
- The next step would be to copy Etch.dll from Etch Home Directory to the server directory.
- Once the file is copied, use csc to compile the *.cs file.
If there are no compile errors MainExampleListener.exe is created. Use the exe file to run the listener.
For the client files, cd to the client directory and follow the same instructions as mentioned above. In csc command replace etch.examples.example.MainExampleListener with
etch.examples.example.MainExampleClient
use MainExampleClient.exe to run the client.
Using Visual Studio
- Please make sure you have followed the steps mentioned in section "Visual Studio Plugin".
- Add %ETCH_HOME%\lib\Etch.dll as a reference to both client and server project
- Build solution by either right clicking on solution and choosing Rebuild Solution or by using keyborad shortcut (CTRL+SHIFT+B).
To Run the Application
- Right click on the server project and chose "Set as Startup Project".
- Press CTRL+F5 to run the listener or server.
- Follow the above two steps to run client as well.
|