Sunday, April 22, 2007

Tok: Chat program in 2 hours.

My DSL line was down for almost a week so I took the chance to get some quality offline-time to brush up on my Groovy. I thought about doing another IRC bot but that's kinda stale as I have done something similar with Ruby.

I want to learn more on SwingBuilder and socket programming with Groovy. And that is when I thought about a simple multiuser chat system. What you are seeing above is Tok, simple chat system written in Groovy. The client and server is done in about 2 hours with Groovy in Action as my guide.

The first thing I did was to get the basic GUI up. As you can see from line 10 and line 21, creating basic Swing panel and frame is very easy. The tricky part is to get the layout right -- line 35. But then again layout has always been a PITA.

For the client server communication I use XML-RPC. It's simple to setup and use in Groovy. Read line 52 - 55. Just start a server and listen for incoming message. The chat server will send updates to everyone who is listening.

The server is a simple server that simply accepts a new client and register it to a list. The "ticket" is simply a serial int number -- indicating the port to be used for the server to connect to the client. See line 27 of the server code.

Well this is a simple chat afterall so you should track by IP and maybe some string token as session control. Anytime a new message is sent from the client, the server will send back the same message to everyone registered in the server list. See line 19.

Tok client
 1 import groovy.swing.SwingBuilder
2 import groovy.net.xmlrpc.XMLRPCServerProxy as Proxy
3 import groovy.net.xmlrpc.XMLRPCServer as Server
4
5 import java.net.ServerSocket
6 import java.awt.BorderLayout as BL
7 import javax.swing.WindowConstants as WC
8
9
10 def swing = new SwingBuilder()
11 def content = new StringBuffer()
12 def remote = new Proxy('http://localhost:8081/')
13
14 newMsg = swing.action( name:'newMessage', closure: {
15 msg = remote.chat( swing.inputMsg.text )
16 //content << "<br> ${msg}"
17 //swing.msgPane.text = content
18 swing.inputMsg.text = ""
19 } )
20
21 def frame = swing.frame( title:'Tok' ) {
22 // Menu bar
23 menuBar {
24 menu('File') {
25 menuItem 'Quit'
26 }
27 menu('Edit') {
28 }
29 menu('Help') {
30 menuItem 'About'
31 }
32 }
33
34 // Panel
35 panel( layout: new BL() ) {
36 scrollPane( constraints: BL.CENTER ) {
37 editorPane( id:'msgPane', editable:false, preferredSize:[60, 100],
38 editorKit: new javax.swing.text.html.HTMLEditorKit() )
39 }
40 panel(constraints: BL.SOUTH) {
41 textField(id:'inputMsg', columns:20)
42 button( action:newMsg, 'Go' )
43 }
44 }
45 }
46 content << "Tok session started on ${new Date().toString()}"
47 swing.msgPane.text = content
48
49 // Perform client registration to the chat network
50 int ticket = remote.register()
51 println "TICKET: ${ticket}"
52 def server = new Server()
53 server.startServer( new ServerSocket(ticket) )
54
55 server.update = { msg ->
56 print msg
57 content << "${msg}"
58 swing.msgPane.text = content
59 }
60
61 frame.pack()
62 frame.setDefaultCloseOperation( WC.EXIT_ON_CLOSE )
63 frame.show()


Tok Server
 1 import groovy.net.xmlrpc.XMLRPCServer as Server
2 import groovy.net.xmlrpc.XMLRPCServerProxy as Proxy
3 import java.net.ServerSocket
4
5
6 def ticket = 9991
7 def clients = []
8
9 def server = new Server()
10
11 server.chat = { msg ->
12 println msg
13 clients.each { client ->
14 //client.update( msg )
15 updateClient(client, msg)
16 }
17 }
18
19 def updateClient(client, msg) {
20 try {
21 client.update( msg )
22 } catch (Exception ex) {
23 println ex
24 }
25 }
26
27 server.register = {
28 clients << new Proxy("http://localhost:${ticket}")
29 return ticket++
30 }
31
32 def socket = new ServerSocket(8081)
33 server.startServer(socket)

2 comments:

mypapit said...

very impressive seymour, i haven't coded swing for quite sometime. your post resurrect my interest in java gui coding (using SwingBuilder)

Anonymous said...

wow, very impressive and fast. i guess ur hell of a programmer

best regards,
eliena
http://visitformoney.blogspot.com