导航

WebSocket搭建一个简单的聊天室

Posted on 2013-04-23 17:37  蝈蝈俊  阅读(2284)  评论(0编辑  收藏  举报

这个例子比较简单:

  • 只有一个聊天室,大家进入的都是同一个聊天室。 
  • 没有用户登录,用户登录直接根据id给出匿名用户。

程序截图,UI我直接用的 https://github.com/Niessy/websocket-golang-chat 这里给的例子的Html代码。

NewImage

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

服务器端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