Last active
December 21, 2015 23:49
-
-
Save wolever/6385162 to your computer and use it in GitHub Desktop.
A simple, incomplete, peer-to-peer chat server in Go written at Go Toronto
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"net" | |
"strings" | |
"bufio" | |
"fmt" | |
) | |
const ( | |
MsgSize = 1024 | |
MaxPeers = 1024 | |
) | |
type OID string; | |
type MID string; | |
type Message struct { | |
oid OID | |
mid MID | |
msg string | |
} | |
type Peer struct { | |
id int | |
cxn net.Conn | |
active bool | |
} | |
func (p *Peer) Close() { | |
p.active = false | |
println("Peer going away:", p.id) | |
} | |
type Server struct { | |
peers []Peer | |
seenMIDs map[MID]bool | |
} | |
func (s *Server) Handle(peerCxn net.Conn) { | |
peer := Peer{len(s.peers), peerCxn, true} | |
println("Peer connected:", peer.id) | |
defer peer.Close() | |
s.peers = append(s.peers, peer) | |
reader := bufio.NewReader(peerCxn) | |
for { | |
line, err := reader.ReadString('\n') | |
if err != nil { | |
println("Read error from peer:", err.Error()) | |
return | |
} | |
line = line[0:len(line) - 1] | |
println("got line:", line) | |
bits := strings.SplitN(line, " ", 3) | |
if len(bits) != 3 { | |
fmt.Printf("Error: invalid line: %v\n", bits) | |
continue | |
} | |
msg := Message{OID(bits[0]), MID(bits[1]), bits[2]} | |
s.SendMessage(msg) | |
} | |
} | |
func (s *Server) SendMessage(m Message) { | |
if s.seenMIDs[m.mid] { | |
return | |
} | |
s.seenMIDs[m.mid] = true | |
println("Got message:", m.msg) | |
toWrite := []byte(string(m.oid) + " " + string(m.mid) + " " + m.msg + "\n") | |
for _, peer := range s.peers { | |
if !peer.active { | |
continue | |
} | |
_, err := peer.cxn.Write(toWrite) | |
if err != nil { | |
println("Error writing to peer:", err.Error()); | |
peer.Close() | |
} | |
} | |
} | |
func main() { | |
svr := Server{make([]Peer, 0, MaxPeers), make(map[MID]bool)} | |
ln, err := net.Listen("tcp", ":6060") | |
if err != nil { | |
println("Listen error:", err.Error()) | |
return | |
} | |
for { | |
cxn, err := ln.Accept() | |
if err != nil { | |
println("Accept error:", err.Error()) | |
continue | |
} | |
go svr.Handle(cxn) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment