Chat server: Difference between revisions

Undo revision 187383 by Wswiss (talk) Does not ocompile
(→‎{{header|Go}}: added synchronization to clients, added logging using package log)
(Undo revision 187383 by Wswiss (talk) Does not ocompile)
Line 536:
 
import (
"bufioos"
"bytes"
"flag"
"fmt"
"log"
"net"
"osflag"
"syncbufio"
"bytes"
)
 
// Quick and dirty error handling.
// A type for storing the connections.
func error_(err error, r int) {
type clientMap struct {
fmt.Printf("Error: %v\n", err)
// the map of names to connections
 
cl map[string]net.Conn
if r >= 0 {
// the mutex protects assoc and dissoc on cl ^
os.Exit(r)
mu sync.RWMutex
}
}
 
// A type for storing the connections.
type clientMap struct {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 error) {
for _, c := range cm.cl {
cm.mu.RLock()
defer cm.mu.RUnlock()
for _, c := range cm.cl {
// Write to each client in a seperate goroutine.
go c.Write(buf)
}
 
n = len(buf)
 
return
}
 
// Check if a name exists; if it doesn't, add it.
func (cm clientMap) AssocAdd(name string, c net.Conn) bool {
for k := range cm {
cm.mu.Lock()
if name == k {
defer cm.mu.Unlock()
return false
if _, e := cm.cl[name]; e {
}
return false
}
 
cm[name] = c
return true
 
return true
func (cm clientMap) Dissoc(name string) {
cm.mu.Lock()
defer cm.mu.Unlock()
delete(cm.cl, name)
}
 
Line 589 ⟶ 587:
func init() {
// Initialize the map.
clients = &clientMap{cl:make(map[string]net.ConnclientMap)}
log.SetPrefix("!server> ")
}
 
Line 599 ⟶ 596:
br := bufio.NewReader(c)
 
retry:
fmt.Fprintf(c, "Please enter your name: ")
 
buf, err := br.ReadBytes('\n')
if err != nil {
log.Printlnerror_("Error: "err, err-1)
return
}
Line 610 ⟶ 606:
 
if name == "" {
fmt.FprintlnFprintf(c, "!!! invalid%v nameis invalid !!!\n", name)
goto retry
}
 
// Try to add the connection to the map.
if !clients.AssocAdd(name, c) {
fmt.Fprintf(c, "!!! %sv is not available !!!\n", name)
return
goto retry
}
 
// Send a message telling the clients who connected.
fmt.Fprintf(clients, "+++ %sv connected +++\n", name)
// Send a disconnected message when the function returns.
defer fmt.Fprintf(clients, "--- %sv disconnected ---\n", name)
// Remove the client from the list.
defer clients.Dissocdelete(clients, name)
 
for {
Line 649 ⟶ 644:
 
// Send the message to all the clients.
fmt.Fprintf(clients, "%sv\n", string(buf))
}
}
 
// Flags. Use -help for usage info.
var (
port = flag.Int("port", 23, "Port to listen on")
help = flag.Bool("help", false, "Display this")
 
func main() {
// Flags. Use -help for usage info.
var (
port int
help bool
)
port = flag.IntIntVar(&port, "port", 23, "Port to listen on")
help = flag.BoolBoolVar(&help, "help", false, "Display this")
flag.Parse()
 
if *help {
flag.Usage()
return
Line 668 ⟶ 664:
 
// Initialize a new listener.
lis, err := net.Listen("tcp", fmt.Sprintf(":%dv", *port))
if err != nil {
log.Fatallnerror_("Error: "err, err1)
}
 
Line 677 ⟶ 673:
c, err := lis.Accept()
if err != nil {
log.Printlnerror_("Error: "err, err-1)
continue
}
Anonymous user