Chat server: Difference between revisions
Content added Content deleted
(Added Go example.) |
(Commented the Go solution.) |
||
Line 161: | Line 161: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
<lang go> |
<lang go> |
||
package main |
|||
import( |
import( |
||
Line 172: | Line 173: | ||
) |
) |
||
// Quick and dirty error handling. |
|||
func error(err os.Error, r int) { |
func error(err os.Error, r int) { |
||
fmt.Printf("Error: %v\n", err) |
fmt.Printf("Error: %v\n", err) |
||
Line 180: | Line 182: | ||
} |
} |
||
// A type for storing the connections. |
|||
type clientMap map[string]net.Conn |
type clientMap map[string]net.Conn |
||
// A method that makes clientMap compatible with io.Writer, allowing it to be |
|||
// used with fmt.Fprintf(). |
|||
func (cm clientMap)Write(buf []byte) (n int, err os.Error) { |
func (cm clientMap)Write(buf []byte) (n int, err os.Error) { |
||
for _, c := range(cm) { |
for _, c := range(cm) { |
||
// Write to each client in a seperate goroutine. |
|||
go c.Write(buf) |
go c.Write(buf) |
||
} |
} |
||
Line 192: | Line 198: | ||
} |
} |
||
// Check if a name exists; if it doesn't, add it. |
|||
func (cm clientMap)Add(name string, c net.Conn) (bool) { |
func (cm clientMap)Add(name string, c net.Conn) (bool) { |
||
for k := range(cm) { |
for k := range(cm) { |
||
Line 204: | Line 211: | ||
} |
} |
||
// A clientMap variable. |
|||
var clients clientMap |
var clients clientMap |
||
func init() { |
func init() { |
||
// Initialize the map. |
|||
clients = make(clientMap) |
clients = make(clientMap) |
||
} |
} |
||
func client(c net.Conn) { |
func client(c net.Conn) { |
||
// Close the connection when this function returns. |
|||
defer c.Close() |
defer c.Close() |
||
Line 228: | Line 238: | ||
} |
} |
||
// Try to add the connection to the map. |
|||
if !clients.Add(name, c) { |
if !clients.Add(name, c) { |
||
fmt.Fprintf(c, "!!! %v is not available !!!\n", name) |
fmt.Fprintf(c, "!!! %v is not available !!!\n", name) |
||
Line 233: | Line 244: | ||
} |
} |
||
// Send a message telling the clients who connected. |
|||
fmt.Fprintf(clients, "+++ %v connected +++\n", name) |
fmt.Fprintf(clients, "+++ %v connected +++\n", name) |
||
// Send a disconnected message when the function returns. |
|||
⚫ | |||
// Only function calls can be defered, so make a function and call it. |
|||
defer func() { |
|||
// Remove the client from the list. |
|||
⚫ | |||
}() |
|||
for { |
for { |
||
Line 242: | Line 262: | ||
buf = bytes.Trim(buf, " \t\n\r\x00") |
buf = bytes.Trim(buf, " \t\n\r\x00") |
||
// Ignore empty messages. |
|||
if len(buf) == 0 { |
if len(buf) == 0 { |
||
continue |
continue |
||
Line 247: | Line 268: | ||
switch { |
switch { |
||
// Support for '/me' type messages. |
|||
case string(buf[0:3]) == "/me": |
case string(buf[0:3]) == "/me": |
||
buf = append([]byte(name), buf[3:]...) |
buf = append([]byte(name), buf[3:]...) |
||
default: |
default: |
||
// Prepend the user-name and '> '. |
|||
buf = append([]byte(name + "> "), buf...) |
buf = append([]byte(name + "> "), buf...) |
||
} |
} |
||
// Send the message to all the clients. |
|||
fmt.Fprintf(clients, "%v\n", string(buf)) |
fmt.Fprintf(clients, "%v\n", string(buf)) |
||
} |
} |
||
⚫ | |||
⚫ | |||
} |
} |
||
func main() { |
func main() { |
||
// Flags. Use -help for usage info. |
|||
⚫ | |||
var( |
|||
⚫ | |||
help bool |
|||
) |
|||
flag.IntVar(&port, "port", 23, "Port to listen on") |
flag.IntVar(&port, "port", 23, "Port to listen on") |
||
flag.BoolVar(&help, "help", false, "Display this") |
|||
flag.Parse() |
flag.Parse() |
||
if help { |
|||
flag.Usage() |
|||
return |
|||
} |
|||
// Initialize a new listener. |
|||
lis, err := net.Listen("tcp", fmt.Sprintf(":%v", port)) |
lis, err := net.Listen("tcp", fmt.Sprintf(":%v", port)) |
||
if err != nil { |
if err != nil { |
||
Line 271: | Line 302: | ||
} |
} |
||
// Begin the main loop. |
|||
for { |
for { |
||
c, err := lis.Accept() |
c, err := lis.Accept() |
||
Line 278: | Line 310: | ||
} |
} |
||
// Launch a new goroutine to handle the connection. |
|||
go client(c) |
go client(c) |
||
} |
} |