Click here to Skip to main content
Email Password   helpLost your password?

Introduction

PrismServer is a complete solution for adding chat and other general purpose multi-user messaging to your .NET applications. The concepts of a chat-enabled application, like creating and entering chat rooms, sending and receiving chat messages, and management of user profiles, are abstracted by PrismServer and made available through simple properties, methods, and events. This code submission consists of the following projects:

ChatNDraw, a sample PrismServer client application

A screen shot of the PrismServer Administrator's console application

Background

PrismServer is the multi-user engine for the Windows based strategy games produced by Silicon Commander Games ("SCG"). SCG has been producing Windows games since the mid 1990s, and several titles allow multiple players to coordinate, create games, and play over the Internet in real-time. SCG needed a general purpose set of components to provide the multi-player feature, and PrismServer was the result.

Originally written as a set of Delphi components, this new version embraces the .NET platform, and the C# programming language. New versions of SCG's popular strategy games are under development, and will use the .NET based PrismServer to provide multi-player capability.

Writing a Client Application

To enable a client application to connect to and communicate via a PrismServer, use the PrismConnection component. In a WinForms application, you can simply drop this component onto the application's form and set the properties in design-time. PrismConnection publishes three properties which must be set prior to connecting:

  1. Host - Specify the domain name or the IP address of the server machine where PrismServer is running.
  2. Port - Specify the port number that the PrismServer is configured to use on the server machine.
  3. SubjectName - The concept of "Subject Name" provides the ability for multiple client applications to utilize a single PrismServer, and only receive the messages that were originated from the same client. PrismServer will route messages only to connected clients that share the same Subject Name. You should provide a string value that corresponds to the name of your application.

Connecting

Once the properties above are set, set the Active property to true to attempt to establish a connection. This action will block the application until a connection is made, or an exception is thrown.

Logging In

Once a connection is established, the next step is to "log in" to the PrismServer using a user name/password. The PrismConnection component offers two methods that can be used to log in to the server: Login and LoginNew. These allow users to log in to the server using a pre-registered user name and password, or as a completely new user, respectively. Your client's user interface should provide paths so that the user can initiate each type of log in.

Call Login to log into the server using a previously registered user name and password. This call is non-blocking. PrismConnection will respond via triggering either the LoginOK event, or the LoginError event. Possible errors are invalid password, and user name not found in the server's registry.

Call LoginNew to log into the server with a new user name. This method takes as a parameter an instance of a PrismUser object, which contains the user information for the new user. The component library contains a PrismUserInfoDialog dialog box component that can be used to quickly create a PrismUser instance. See the ChatNDraw demo client application to see this component in action. The call is non-blocking, and PrismConnection will respond by triggering either the LoginOK event or the LoginError event. Possible errors include the specified user name already exists, or an invalid user name specified.

In your client application, you can always retrieve the instance of the local PrismUser that is connected by referencing the ThisUser property.

//Sample PrismServer client connection code
connection.Host = _frmLogin.txtHost.Text;
connection.Port = (int)_frmLogin.numPort.Value;
try
{
   connection.Active = true;
   connection.Login(_frmLogin.txtUserName.Text, _frmLogin.txtPassword.Text);
}
catch (Exception error)
{
   MessageBox.Show(error.Message, "PrismServer Connection Error");
}

PrismRooms

Each client connected to a PrismServer occupies a single PrismRoom, and can chat and interact only with other clients within the same room. Your client application can see all of the PrismRooms that have been created that share its Subject Name.

The PrismConnection component notifies the client of newly created PrismRooms via the RoomAdded event. You should expect to receive a series of these events immediately after a successful log-in, one for each PrismRoom that currently exists on the server. The client should represent the rooms in the user interface, using a ListBox, ListView, or similar control. When a PrismRoom is removed, PrismConnection notifies the client via a RoomRemoved event.

PrismConnection also notifies the client when users enter and leave PrismRooms. This is accomplished via the UserAddedToRoom and UserLeftRoom events.

After successful log in, the client is placed into a default room, or lobby. PrismConnection notifies that client that it has entered a new room via the JoinedRoom event. Note that JoinedRoom is triggered, in addition to an accompanying UserAddedToRoom event; the UserAddedToRoom containing the PrismUser object that represents the client that is actually connected in the local application (the same instance as the ThisUser property).

To join a different PrismRoom, call the EnterRoom method. To create a new PrismRoom, call the CreateRoom method. These calls are non-blocking, but do not place you into the new room immediately. After calling one of the methods, you should expect to receive several events, UserLeftRoom (indicating that you have left your current room), UserAddedToRoom (indicating that you have entered the new room), and finally JoinedRoom. Also, if you are the last user to leave a room, PrismServer will destroy the room (unless it is the default lobby) and PrismConnection will trigger the RoomRemoved event. If you create a new room, you will receive the RoomAdded event prior to UserAddedToRoom and JoinedRoom.

PrismRooms for Multi-Player Games

The CreateRoom method has two parameters, the desired room name and the maximum number of participants that the room can hold (specify 0 to indicate no maximum number). If you pass a number greater than zero, PrismConnection will trigger a StartSignal event when the indicated number of participants have entered the room, and the server will lock the room so no other clients can enter it. This feature is designed to allow multi-player games to kick off once the specified number of players have entered the game room.

Chat and Data Messages

When you are in a PrismRoom, you can exchange chat and data messages with the other clients in the room. To send a string of chat text, call the SendChat method. When a string of chat text is received from other clients in the room (note that this excludes the local client), PrismConnection triggers the ChatMessageReceived event.

"Data Messages" are also strings that can be sent to clients in the room, and are handled in a similar way to chat strings. The idea behind Data Messages is to provide a facility for client applications to pass application-specific, non-chat, data to clients in the room. Call SendData to send a Data Message, and respond to incoming Data Messages by handling the DataMessageRecieved event.

ChatNDraw Client

Included is the complete source code for a simple client application, ChatNDraw. This sample client allows users to connect to a PrismServer, create and join chat rooms, chat with other users, and draw on a shared blackboard. Some points of interest:

Writing a Server Application

The PrismServer component is the basis of a PrismServer server application. It encapsulates the multi-threaded server socket, management of Subject Names, PrismRooms, and PrismUsers, and handles routing of messages to connected clients. The PrismServer components offers a number of properties to control aspects of the server's behavior:

The PrismServer component also offers some methods that allow the operator to interact with the server and connected clients, as well as a series of events. Server applications should respond to these events to update their user interfaces to reflect the modified information (new clients connecting, rooms added or removed, etc.) See the included PrismServerAdmin application for a sample server application that performs these actions.

User Management in PrismServer

The PrismServer component exposes an Implementation property that must be assigned to a component that derives from the virtual PrismServerImplementation. PrismServerImplementation provides an interface for user management. You can derive a new component from PrismServerImplementation to allow the server to use a local file, a database, or any other storage mechanism desired to manage user information. This storage mechanism which is defined by the derived class will be referred to subsequently as the "user registry", this does not correspond to the Windows registry. Included in the package is a simple concrete descendant that you can use out of the box: PrismServerFileImplementation. This component stores user information in simple binary files on the local file system.

The PrismServerImplementation component contains the following methods that should be overridden to produce a working user management implementation:

Under the Hood

Both the client (PrismConnection component) and server (PrismServer component) sides of PrismServer use a utility class called PrismNetworkStream to manage reading and writing data from the connected socket. PrismNetworkStream is responsible for reading and writing the raw bytes from and to the underlying socket. Internally, PrismServer uses a text-based transport protocol and passes information among clients as strings. Each string message is composed of a length header, followed by a pipe (|) delimiter, then the remainder of the message. For example, a message containing the text "My Message" would flow through the socket as the following string:

9|MyMessage

Built upon this simple transport protocol, PrismServer uses its own internal protocol for messaging. Each message begins with a "type" qualifier, followed by zero to many parameters. For example, when the client sends a line of chat text to the server (the SendChat method), the following command is sent to the transport protocol (which appends the message length, then sends it to the server socket),

CHAT|This is my chat message!

becomes:

29|CHAT|This is my chat message!

When the server receives the message, it propagates it to the remainder of the clients that are in the same PrismRoom. However, it needs to append the user name of the client that typed in the chat message so this can be communicated to the other clients. The server responds by sending the following back to other clients in the room:

CHAT|UserName|This is my chat message!

becomes:

38|CHAT|This is my chat message!

When the PrismConnection component receives this message, it ultimately fires the ChatMessageReceived event, with two parameters indicating the PrismUser (based on the UserName in the string) and the message text itself.

The complete PrismServer protocol is briefly outlined in the PrismProtocol.txt file included in the download.

Thread Safety Issues

Both primary components, PrismConnection (for client side applications) and PrismServer (for server applications) make heavy use of .NET events to communicate actions to their host applications. For example, PrismConnection fires a RoomAdded event when a new chat room was created by someone who is logged in under the same Subject Name. It is tempting to simply provide an event handler for this event and add the room name to a ListBox on the main form's user interface. However, the events that are fired occur in the context of a different thread. Trying to update a GDI+ user interface element in a different thread will result in an InvalidOperationException.

You should ensure that any code that updates user interface elements occurs in the main UI thread. The PrismServerAdmin application tackles this by maintaining several Queues that the event handlers add items to (in a thread-safe manner, via a lock statement). On the main form, a Timer component continuously runs (on the main UI thread), and pulls the items out of the Queues and into the UI elements.

ChatNDraw takes a different approach. It uses a short-cut by setting Control.CheckForIllegalCrossThreadCalls to false, bypassing this restriction. This action is typically not recommended, but since ChatNDraw's UI is only ever modified by the single external thread in the PrismConnection component, it was deemed a safe approach in this case. If there is ever any chance of UI elements being changed by different threads, using this flag is not recommended, and the calls should be routed through delegates using the Control class' Invoke method.

Update 5.1

In the 5.1 release, I have beefed up the thread safety of the PrismServer admin console, after I discovered some flaws in the initial release. As a general rule of thumb, I should also point users to the Invoke method of the Control class in the .NET Framework. If you need to call a method that interacts with UI controls from a different thread, you should use the Invoke method - check the .NET Framework docs for details.

History

18th July, 2007

6th May, 2008

I will maintain the official source code release for PrismServer on the Silicon Commander Games Web site. Noteworthy enhancements and fixes that are contributed will be rolled into the source code as version releases.

I am interested in the following types of contributions:

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionPrivate chatting
Shahnewaz Rico
3:01 12 May '09  
Hi,

Can I develop private chatting within the same application ?
If possible, please give me some suggestion (if possible).

Thanks for your great job.

Best Regards,

Shahnewaz Rico.
GeneralIs it possible to create a PHP server for LAMP and use PrismClient
Navedac
23:04 2 May '09  
Hello.

PrismServer run only on windows.

Is it possible to create the Server with script PHP to simule Server Prism ?

Thanks for reply

Navedac

Try it www.furukoo.fr with your friends.
GeneralHelp.
Mr. Pravin S Chavare
10:00 9 Mar '09  
Congrats .......... This is a very good project for the ASP.NET beginers like me.

Well I have tested this SCG PrismServer ChatNDraw application in LAN.

Now I have questions as follows:

1. How to modify this project so that it can be used as a Web Based CHAT application.

2. Also how to display the New pop-up Window at each Sender's end and Receiver's end.

I mean to say that How to generate them DYNAMICALLY.

Also they must be properly diposed so that no any overload takes place.
QuestionThanks and need help
manjeet pimpale
22:43 20 Feb '09  
HI,
First of all I am thankfull for your best application i.e. ChatNDraw.

But I have some queries regarding,

1. can we use MySQL as database for it? How?

2. can we develop private chatting within the same application ? How?


Your help will be precious for me. I am student of Computer Science, learning MySQL 5.1 version and want to develop the messenger like Yahoo etc. So your help will be very much needy for me. Thanks in ADVANCE......

Nice work, Keep it up which will guide the begginners like me.

I am using vs 2005, .net frame work 2.0...


My E-Mail ID ispimpale_man@rediffmail.com<a href="">pimpale_manjeet@yahoo.co.in</a>
AnswerRe: Thanks and need help
Dion Kurczek
13:19 1 Apr '09  
Sure, you can use any kind of back end storage to maintain user information. The design is flexible, and the text-based solution is there only as an example. To create your own storage for PrismServer, create a new Component and have it extend the PrismServerImplementation component. Then, override the virtual methods to implement the logic behind your storage.

To tell the PrismServer to use your implementation, drop your component on the server form, them assign it in the Implementation property of the PrismServer component. Let me know if you need any more clarifications.
QuestionHow to run this application?
rajesh kumar swain
0:43 2 Feb '09  
Hi,

This application is great. But I am facing a problem while running it. I have downloaded the files and tried running it. But it shows me an error. The error is as following...

A project with output type of class library cannot be start directly.
In order to debug the project add an executable project to this solution which references the library project. Set the executable project as startup project.

Waiting for your reply.
AnswerRe: How to run this application?
manjeet pimpale
22:33 24 Feb '09  
Its simple just unzip the file you will get 3 folders. ChatNDraw,PrismServer,SCG.Prism
open visual studio and click on file->open->project then it will browse for folder then choose folder 'SCG.Prism' and choose project file then click ok then all 3 projects will be shown in solution explorer. After this you have to build it only; then you will get executable files in '\PrismServer\bin\Debug' and '\ChatNDraw\bin\Debug' for server and user respectively.....thats it! Big Grin
GeneralRe: How to run this application?
Dion Kurczek
13:11 1 Apr '09  
You can also tell Visual Studio which project to run as the default project. Right click on the ChatNDraw or the PrismServer Admin project in VS and select Set as Startup Project. Then, when you click run, that project will run.
GeneralUrgent Help
harikrishna210
20:26 19 Nov '08  
Hi Dion
You have done a great job.
I tried to run the application but i am just confused how to use it out of box. I could not understant how to use it as chatting application.How to go about it. Please help me in using ur great work. how to run server and how to connect to it as client.where to mention that i am a server or client
Loooking forward for ur immediate response
thanks in advance
hari krishna
padmanabhan.harikrishna@gmail.com
GeneralRe: Urgent Help
manjeet pimpale
22:36 24 Feb '09  
Its simple just unzip the file you will get 3 folders. ChatNDraw,PrismServer,SCG.Prism
open visual studio and click on file->open->project then it will browse for folder then choose folder 'SCG.Prism' and choose project file then click ok then all 3 projects will be shown in solution explorer. After this you have to build it only; then you will get executable files in '\PrismServer\bin\Debug' and '\ChatNDraw\bin\Debug' for server and user respectively.....thats it! Big Grin



if questions persists then send it to me!!!!!!
GeneralFurukoo
Navedac
2:24 21 Sep '08  
I use your server to made a play.

Source code is here :

http://www.vbfrance.com/code.aspx?ID=48012[^]

Thanks for your job

Afyn - Navedac
Generalwonderful
heavymay
23:07 22 Jun '08  
ow,that's good.i'm learning it.
may be i will ask you some questions next time.
thank you! Smile

study

GeneralRe: wonderful
Dion Kurczek
12:20 25 Jun '08  
Sure thing, let me know if I can be of any help.
Generalhi i want to use it for learning C#
Member 3815566
0:08 7 Mar '08  
hi
sir can you tell me how to add selective erase,pencil tool for drawing,changing thickness of pencil,i want to put map baground .

thanking you


RAVI MR
mr.ravi1230@gmail.com
GeneralRe: hi i want to use it for learning C#
Dion Kurczek
14:30 6 May '08  
You'd need to use the SendData method of the PrismConnection component to create new commands and send them to clients. Then, in the DataMessageReceived event, handle your messages. You can see an example by looking at the Clear and the Set Color buttons. I create my own Data commands and respond to them. You just need to create your own commands and parameters using this model to do what you need.
GeneralMysql and the usernames?
zagitta
6:00 17 Jan '08  
Hi Smile is there any way that i can make this work with mysql instead of some simple .pru files with normal text encoding? becuase that would be a lot more secure and give some more preformance with many users Wink


BTW thx Smile for the great work Big Grin
GeneralRe: Mysql and the usernames?
Dion Kurczek
14:32 6 May '08  
Yes, just derive a new component from PrismServerImplementation, override the virtual methods, then drop it on the server form. Make sure to set the "Implementation" property of the PrismServer component to point to your implementation component.
GeneralHow adjust ip adress parameter ?
Navedac
9:55 25 Dec '07  
Hello

I try to run your serveur.
No problem in localhost.
Serveur and client on the same computer.

If i want connect by internet what do i must do to adjust ip adress ?
(change in the source code) ?
Serveur on a computer
Client on another computer in an another town ...

Thank for respons

Navedac
GeneralRe: How adjust ip adress parameter ?
Dion Kurczek
14:33 6 May '08  
Sorry I took so long to respond, but do you still need help with this problem?
Generallogin error
moshesag
22:15 31 Oct '07  
i recive this error -
a connection attempt failed because the connected party did not properly respond after a period of time or established connection failed because connected host has failed to respond
when i put prism server at remote server and i try to connect from my comuter


QuestionDoesn't do anything [modified]
Jim Weiler
9:49 21 Sep '07  
I have yet to look at any of the source, but after compiling the project, running the server and client, and connecting to localhost (also tried 127.0.0.1) : 4000, nothing ever happens. I get the same results whether I am trying to create a user or just connect. If I stop the server, I do get an error in the client so there is a connection. The server stats never change, nothing is logged, nothing happens on the client. I connected to the server with a terminal and nothing was ever received from it. Does this not work out of the box?


-- modified at 16:48 Friday 21st September, 2007
Ok so I just tried on another PC and it works fine. Must be filtering it on my laptop. I'll look into it later.

Another comment though, was there a reason for not allowing a user to exist in more than 1 room at a time?

-Jim

Generalmesagges with color
Britney S. Morales
3:33 13 Sep '07  
Can i give different color for the users messages? Smile

keep Learning and you never will be out of date...

NewsHelp if you want
fermar84
17:56 8 Aug '07  
Hey Dion, i hope you remember me. It's fernando from Colombia. I think i can help you, i have experience with .NET, C# and VB. You can contact me to fermar84@hotmail.com , so if you need any help you can count on me.

Sincerely,
Fernando

Fernando Martinez Mendoza
Bucaramanga - Colombia

GeneralRe: Help if you want
Dion Kurczek
14:34 6 May '08  
Fernando, nice to hear from you again! You still there?
GeneralRe: Help if you want
fermar84
15:44 6 May '08  
hey Dion, wasup!!! Yes i'm still out here. My email is like always fermar84@hotmail.com
Long time no seeing you.

Fernando Martinez Mendoza
Bucaramanga - Colombia


Last Updated 8 May 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010