Montag, 14. Dezember 2009

simpler chat server and client in golang

server:

package main

import (
"fmt";
"net";
"log";
"os";
"container/list";
"strings";
"bytes";
"flag";
)

// flag for debuging info. or a simple log
var debug = flag.Bool("d", false, "set the debug modus( print informations )")

type ClientChat struct {
Name string; // name of user
IN chan string; // input channel for to send to user
OUT chan string; // input channel from user to all
Con *net.Conn; // connection of client
Quit chan bool; // quit channel for all goroutines
ListChain *list.List; // reference to list
}

// read from connection and return true if ok
func (c *ClientChat) Read(buf []byte) bool{
nr, err := c.Con.Read(buf);
if err!=nil {
c.Close();
return false;
}
Log("Read(): ", nr, " bytes");
return true;
}

// close the connection and send quit to sender
func (c *ClientChat) Close() {
c.Quit<-true;
c.Con.Close();
c.deleteFromList();
}

// compare two clients: name and network connection
func (c *ClientChat) Equal(cl *ClientChat) bool {
if bytes.Equal(strings.Bytes(c.Name), strings.Bytes(cl.Name)) {
if c.Con == cl.Con {
return true;
}
}
return false;
}

// delete the client from list
func (c *ClientChat) deleteFromList() {
for e := c.ListChain.Front(); e != nil; e = e.Next() {
client := e.Value.(ClientChat);
if c.Equal(&client) {
Log("deleteFromList(): ", c.Name);
c.ListChain.Remove(e);
}
}
}

// func Log(v ...): loging. give log information if debug is true
func Log(v ...) {
if *debug == true {
ret := fmt.Sprint(v);
log.Stdoutf("SERVER: %s", ret);
}
}

// func test(): testing for error
func test(err os.Error, mesg string) {
if err!=nil {
log.Stderr("SERVER: ERROR: ", mesg);
os.Exit(-1);
} else
Log("Ok: ", mesg);
}

// handlingINOUT(): handle inputs from client, and send it to all other client via channels.
func handlingINOUT(IN <-chan string, lst *list.List) {
for {
Log("handlingINOUT(): wait for input");
input := <-IN; // input, get from client
// send to all client back
Log("handlingINOUT(): handling input: ", input);
for value := range lst.Iter() {
client := value.(ClientChat);
Log("handlingINOUT(): send to client: ", client.Name);
client.IN<- input;
}
}
}



// clientreceiver wait for an input from network, after geting data it send to
// handlingINOUT via a channel.
func clientreceiver(client *ClientChat) {
buf := make([]byte, 2048);

Log("clientreceiver(): start for: ", client.Name);
for client.Read(buf) {

if bytes.Equal(buf, strings.Bytes("/quit")) {
client.Close();
break;
}
Log("clientreceiver(): received from ",client.Name, " (", string(buf), ")");
send := client.Name+"> "+string(buf);
client.OUT<- send;
for i:=0; i<2048;i++ {
buf[i]=0x00;
}
}

client.OUT <- client.Name+" has left chat";
Log("clientreceiver(): stop for: ", client.Name);
}

// clientsender(): get the data from handlingINOUT via channel (or quit signal from
// clientreceiver) and send it via network
func clientsender(client *ClientChat) {
Log("clientsender(): start for: ", client.Name);
for {
Log("clientsender(): wait for input to send");
select {
case buf := <- client.IN:
Log("clientsender(): send to \"", client.Name, "\": ", string(buf));
client.Con.Write(strings.Bytes(buf));
case <-client.Quit:
Log("clientsender(): client want to quit");
client.Con.Close();
break;
}
}
Log("clientsender(): stop for: ", client.Name);
}

// clientHandling(): get the username and create the clientsturct
// start the clientsender/receiver, add client to list.
func clientHandling(con *net.Conn, ch chan string, lst *list.List) {
buf := make([]byte, 1024);
con.Read(buf);
name := string(buf);
newclient := &ClientChat{name, make(chan string), ch, con, make(chan bool), lst};

Log("clientHandling(): for ", name);
go clientsender(newclient);
go clientreceiver(newclient);
lst.PushBack(*newclient);
ch<- name+" has joinet the chat";
}

func main() {
flag.Parse();
Log("main(): start");

// create the list of clients
clientlist := list.New();
in := make(chan string);
Log("main(): start handlingINOUT()");
go handlingINOUT(in, clientlist);

// create the connection
netlisten, err := net.Listen("tcp", "127.0.0.1:9988");
test(err, "main Listen");
defer netlisten.Close();

for {
// wait for clients
Log("main(): wait for client ...");
conn, err := netlisten.Accept();
test(err, "main: Accept for client");
go clientHandling(&conn, in, clientlist);
}
}


Server has three part which are running as goroutines and communicate via channels.
1) handlingINOUT() simple wait for input of clientreceiver() and send to all clientsender() which are in the list.
2) clientreceiver() wait for his data from client via networkconnection and send it to a inputchannel to handlingINOUT
3) clientsender() wait for data from channel and send it to client

every client connection get a his own clientreceiver/sender and a list entry. on disconnection the list entry will be deleted.


client:

package main

import (
"fmt";
"net";
"log";
"os";
"bytes";
"bufio";
"strings";
"time";
"flag";
)

var running bool; // global variable if client is running

var debug = flag.Bool("d", false, "set the debug modus( print informations )")

// func Log(v ...): loging. give log information if debug is true
func Log(v ...) {
if *debug == true {
ret := fmt.Sprint(v);
log.Stdoutf("CLIENT: %s", ret);
}
}

// func test(): testing for error
func test(err os.Error, mesg string) {
if err!=nil {
log.Stderr("CLIENT: ERROR: ", mesg);
os.Exit(-1);
} else
Log("Ok: ", mesg);
}

// read from connection and return true if ok
func Read(con *net.Conn) string{
var buf [4048]byte;
_, err := con.Read(&buf);
if err!=nil {
con.Close();
running=false;
return "Error in reading!";
}
str := string(&buf);
fmt.Println();
return string(str);
}

// clientsender(): read from stdin and send it via network
func clientsender(cn *net.Conn) {
reader := bufio.NewReader(os.Stdin);
for {
fmt.Print("you> ");
input, _ := reader.ReadBytes('\n');
if bytes.Equal(input, strings.Bytes("/quit\n")) {
cn.Write(strings.Bytes("/quit"));
running = false;
break;
}
Log("clientsender(): send: ", string(input[0:len(input)-1]));
cn.Write(input[0:len(input)-1]);
}
}

// clientreceiver(): wait for input from network and print it out
func clientreceiver(cn *net.Conn) {
for running {
fmt.Println(Read(cn));
fmt.Print("you> ");
}
}

func main() {
flag.Parse();
running = true;
Log("main(): start ");

// connect
destination := "127.0.0.1:9988";
Log("main(): connecto to ", destination);
cn, err := net.Dial("tcp", "", destination);
test(err, "dialing");
defer cn.Close();
Log("main(): connected ");

// get the user name
fmt.Print("Please give you name: ");
reader := bufio.NewReader(os.Stdin);
name, _ := reader.ReadBytes('\n');

//cn.Write(strings.Bytes("User: "));
cn.Write(name[0:len(name)-1]);

// start receiver and sender
Log("main(): start receiver");
go clientreceiver(&cn);
Log("main(): start sender");
go clientsender(&cn);

// wait for quiting (/quit). run until running is true
for ;running; {
time.Sleep(1*1e9);
}
Log("main(): stoped");
}


client start two goroutines: for getting input from stdin and send it to network. and get from network and print it out.

Freitag, 11. Dezember 2009

simple server/client

a simple server and client in golang.

server wait for a client and handle him, simple read and write, then close.

client connect to server, write then read to/from server.

server:

package main

import (
. "fmt";
"net";
"os"; "log";
"strings";
)

func test(err os.Error, mesg string) {
if err!=nil {
log.Stderr("SERVER: ERROR: ", mesg);
os.Exit(-1);
} else
log.Stdout("SERVER: OK: ", mesg);
}


func main() {
buf := make([] byte, 1500);

Println("starting server...");

netlisten, err := net.Listen("tcp", "127.0.0.1:9988");
test(err, "Listen");
defer netlisten.Close();

for{
Println("server wait for client ...");
con, err := netlisten.Accept();
test(err, "Accept for client");
Println("client has connect to server");

con.Read(buf);

Println("readed: ", string(buf));

con.Write(strings.Bytes("response from server"));
}
}


client:

package main

import (
. "fmt";
"net";
"os"; "log";
)

func test(err os.Error, mesg string) {
if err!=nil {
log.Stderr("CLIENT: ERROR: ", mesg);
os.Exit(-1);
} else
log.Stdout("CLIENT: OK: ", mesg);
}

func main() {
buf := make([] byte, 1500);

Println("starting client");
con, err := net.Dial("tcp", "", "127.0.0.1:9988");
test(err, "dialing");
defer con.Close();
Println("client has connected to server");

con.Write(strings.Bytes("das ist ein test"));

con.Read(buf);

Println("readed: ", string(buf));
}

Donnerstag, 10. Dezember 2009

Golang: crypto/aes

Here we test the golang aes encryption decryption. We simple encrypt and decrypt a text message with AES-128. That is a key with 16 byte length.

"NewCipher creates and returns a new Cipher. The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256."


package main

import (
"crypto/aes";
. "fmt";
"os";
"strings";
)

func main() {
// a 32 byte long message
msg := "This is long message text. len32";
// some key, 16 Byte long
key := []byte{0x2c, 0x88, 0x25, 0x1a, 0xaa, 0xae, 0xc2, 0xa2, 0xaf, 0xe7, 0x84, 0x8a, 0x10, 0xcf, 0xe3, 0x2a};

Println("len of message: ", len(msg));
Println("len of key: ", len(key));
// create the new cipher
c, err := aes.NewCipher(key);
if err != nil {
Println("Error: NewCipher(%d bytes) = %s", len(key), err);
os.Exit(-1);
}

// now we convert our string into 32 long byte array
msgbuf := strings.Bytes(msg);
out := make([]byte, len(msg));

c.Encrypt(msgbuf[0:16], out[0:16]); // encrypt the first half
c.Encrypt(msgbuf[16:32], out[16:32]); // encrypt the second half

Println("len of encrypted: ", len(out));
Println(">> ", out);

// now we decrypt our encrypted text
plain := make([]byte, len(out));
c.Decrypt(out[0:16], plain[0:16]); // decrypt the first half
c.Decrypt(out[16:32], plain[16:32]); // decrypt the second half

Println("msg: ", string(plain));
}

output:

len of message: 32
len of key: 16
len of encrypted: 32
>> [0 173 125 174 152 165 226 181 32 25 196 177 81 243 134 79 55 152 215 72 239 85 123 219 82 30 231 89 185 194 67 203]
msg: This is long message text. len32

Mittwoch, 9. Dezember 2009

Container in Go: ring

Ring:

A Ring is an element of a circular list, or ring. Rings do not have a beginning or end; a pointer to any ring element serves as reference to the entire ring. Empty rings are represented as nil Ring pointers. The zero value for a Ring is a one-element ring with a nil Value.


package main

import (
. "fmt";
"container/ring";
"strings";
"bytes";
)

// print the elements of the ring
func PrintRing(r *ring.Ring) {
Println("------------------------------");
for value := range r.Iter() {
Println("value: ", value);
}
Println("------------------------------");
}

func main() {
// create a new ring with 10 items
r := ring.New(10);

Println("len of ring: ", r.Len());
PrintRing(r);

// set some value
r.Value = "value 1";
// take the next

r = r.Next();
r.Value = "value 2";

r = r.Next();
r.Value = "value 3";

r = r.Next();
r.Value = "value 4";

PrintRing(r);


// create a second ring with 3 item and set his value
r2 := ring.New(3);
r2.Value = "r2 value 1";
r2 = r2.Next();
r2.Value = "r2 value 2";
r2 = r2.Next();
r2.Value = "r2 value 3";
PrintRing(r2);

// merge ring2 into ring 1
r = r.Link(r2);
PrintRing(r);

// remove a value in ring
for p:=r.Next(); p!=r; p=p.Next() {
if p.Value != nil {
value := p.Value.(string);
if bytes.Equal(strings.Bytes(value),strings.Bytes("r2 value 2")) {
p.Value=nil;
}
}
}

PrintRing(r);
}

output:

len of ring: 10
------------------------------
value:
value:
value:
value:
value:
value:
value:
value:
value:
value:
------------------------------
------------------------------
value: value 4
value:
value:
value:
value:
value:
value:
value: value 1
value: value 2
value: value 3
------------------------------
------------------------------
value: r2 value 3
value: r2 value 1
value: r2 value 2
------------------------------
------------------------------
value:
value:
value:
value:
value:
value:
value: value 1
value: value 2
value: value 3
value: value 4
value: r2 value 3
value: r2 value 1
value: r2 value 2
------------------------------
------------------------------
value:
value:
value:
value:
value:
value:
value: value 1
value: value 2
value: value 3
value: value 4
value: r2 value 3
value: r2 value 1
value:
------------------------------

Montag, 7. Dezember 2009

Container in Go: list

List: (a doubly linked list)

The list is a double linked list of Elements. Element is an element in the linked list with Next() and Prev() pointer to other elements. Begining and ending of Elements are nil.


package main

import (
. "fmt";
"container/list";
"strings";
"bytes";
)

// print the elements of the list
func PrintList(l *list.List) {
Println("------------------------------");
for value := range l.Iter() {
Println("element: ", value);
}
Println("------------------------------");
}

func main() {
// create a new list
li := list.New();

// add elements at end
li.PushBack("list1");
li.PushBack("list2");

// add elements at begining
li.PushFront("list3");

PrintList(li);

// get the first element from the list
element := li.Front();
str := element.Value;
Println("value: ", str);

// add a element before the first element
li.InsertBefore("list4", element);

// add after the element
li.InsertAfter("list5", element);

PrintList(li);

// get the next element
element = element.Next();
Println("value: ", element.Value);

// move the first element to back
element = li.Front();
li.MoveToBack(element);

PrintList(li);

// remove the first element
element = li.Front();
li.Remove(element);

PrintList(li);

// find the element with "list2" and remove it
for element := li.Front(); element != nil; element = element.Next() {
// don't use li.Iter(), because the interface chanel
// is geting the Value from the element back. not the element.
value := element.Value.(string);

if bytes.Equal(strings.Bytes(value),strings.Bytes("list2")) {
li.Remove(element);
}
}

PrintList(li);

}


the output is:

------------------------------
element: list3
element: list1
element: list2
------------------------------
value: list3
------------------------------
element: list4
element: list3
element: list5
element: list1
element: list2
------------------------------
value: list5
------------------------------
element: list3
element: list5
element: list1
element: list2
element: list4
------------------------------
------------------------------
element: list5
element: list1
element: list2
element: list4
------------------------------
------------------------------
element: list5
element: list1
element: list4
------------------------------