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