这个例子比较简单:
- 只有一个聊天室,大家进入的都是同一个聊天室。
- 没有用户登录,用户登录直接根据id给出匿名用户。
程序截图,UI我直接用的 https://github.com/Niessy/websocket-golang-chat 这里给的例子的Html代码。
服务器端Golang代码:
package main
import (
"code.google.com/p/go.net/websocket"
"container/list"
"fmt"
"html/template"
"log"
"net/http"
"os"
)
const (
listenAddr = "localhost:4000" // server address
)
var (
pwd, _ = os.Getwd()
RootTemp = template.Must(template.ParseFiles(pwd + "/chat.html"))
activeClients *list.List
connid int
)
// RootHandler renders the template for the root page
func RootHandler(w http.ResponseWriter, req *http.Request) {
err := RootTemp.Execute(w, listenAddr)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
// WebSocket server to handle chat between clients
func SockServer(ws *websocket.Conn) {
var err error
var clientMessage string
// cleanup on server side
defer func() {
if err = ws.Close(); err != nil {
log.Println("Websocket could not be closed", err.Error())
}
}()
client := ws.Request().RemoteAddr
fmt.Println("Client connected:", client)
connid++
id := connid
clientUserName := fmt.Sprintf("guest %d", id)
fmt.Println("Client username:", clientUserName)
item := activeClients.PushBack(ws)
defer activeClients.Remove(item)
SendMessage(nil, fmt.Sprintf("welcome %s join\n", clientUserName))
// for loop so the websocket stays open otherwise
// it'll close after one Receieve and Send
for {
if err = websocket.Message.Receive(ws, &clientMessage); err != nil {
// If we cannot Read then the connection is closed
fmt.Println("Websocket Disconnected waiting", err.Error())
fmt.Println("Number of clients still connected ...", activeClients.Len())
return
}
clientMessage = fmt.Sprintf("%s %s > %s", client, clientUserName, clientMessage)
fmt.Println(clientMessage)
SendMessage(ws, clientMessage)
}
}
func SendMessage(self *websocket.Conn, data string) {
for item := activeClients.Front(); item != nil; item = item.Next() {
ws, ok := item.Value.(*websocket.Conn)
if !ok {
panic("item not *websocket.Conn")
}
if item.Value == self {
continue
}
websocket.Message.Send(ws, data)
}
}
// Initialize handlers and websocket handlers
func init() {
http.HandleFunc("/", RootHandler)
http.Handle("/sock", websocket.Handler(SockServer))
}
func main() {
activeClients = list.New()
err := http.ListenAndServe(listenAddr, nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
页面模版(chat.html)
使用模版就是为了避免服务器地址在多个地方配置,只要在一个地方配置即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title> WebSockets </title>
<style>
* {
padding: 0px;
margin: 0px;
}
body {
width:100%;
font-family: fantasy;
font-size: 13px;
}
h1 {
text-align: center;
}
#text {
position: relative;
left: 500px;
top: 20px;
}
#chat-box-container {
width: 600px;
height: 100%;
position: relative;
left: 500px;
top: 50px;
}
#chatbox {
position: relative;
right: 150px;
border-style: solid;
border-radius: 2px;
padding: 10px;
}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script>
try {
var sock = new WebSocket("ws://{{.}}/sock");
//sock.binaryType = 'blob'; // can set it to 'blob' or 'arraybuffer
console.log("Websocket - status: " + sock.readyState);
sock.onopen = function(m) {
console.log("CONNECTION opened..." + this.readyState);}
sock.onmessage = function(m) {
$('#chatbox').append('<p>' + m.data + '</p>');}
sock.onerror = function(m) {
console.log("Error occured sending..." + m.data);}
sock.onclose = function(m) {
console.log("Disconnected - status " + this.readyState);}
} catch(exception) {
console.log(exception);
}
</script>
</head>
<body>
<h1> This chat is powered by web sockets </h1>
<div id ="text">
<textarea id="textin" cols="30" rows="4" placeholder="This is where you type..." autofocus>
</textarea>
<button id="send">Send Message</button>
</div>
<divid="chat-box-container">
<h2> This is the chatbox... </h2>
<div id="chatbox">
<p> Go Type stuff... </p>
</div>
</div>
<script>
$('#textin').val("");
// take what's the textbox and send it off
$('#send').click( function(event) {
var txt = $('#textin').val()
sock.send(txt);
$('#textin').val("");
$('#chatbox').append('<p> I said ' + txt + '</p>');
});
</script>
</body>
</html>
参考资料:
一个Go语言实现的聊天室。
https://github.com/square/SocketRocket/blob/master/TestChatServer/go/chatroom.go
websocket-golang-chat
https://github.com/Niessy/websocket-golang-chat
使用 Go 语言和 HTML5 WebSocket 构建一个 Web 聊天室
http://www.oschina.net/translate/10-techforce-building-a-web-chat-with-the-go-programming-language-and-html5-websockets?print
http://theplant.jp/en/blogs/10-techforce-building-a-web-chat-with-the-go-programming-language-and-html5-websockets
https://github.com/kobeld/gochatting
在golang中,html5,使用websocket,建立一个最简单的高并发web聊天室
http://www.cppblog.com/AutomateProgram/archive/2012/12/20/196481.html
jmcvetta / tokenizerd A data tokenization server
https://github.com/jmcvetta/tokenizerd
Implementing Chat with WebSockets and Go
http://gary.beagledreams.com/page/go-websocket-chat.html
golang websocket 简易聊天室
http://www.dotcoo.com/golang-websocket-chatroom
Polemo Chat客户端行为
http://www.cnblogs.com/yjf512/archive/2013/02/19/2916810.html