Although PhantomJS version 1.9 does have WebSocket support, that support is limited to the hixie-76 draft of the protocol. PhantomJS 2.0 is scheduled to include the more modern RFC 6455 version of WebSockets. When writing scripts for PhantomJS that intend to use WebSocket connections, we must ensure that the server supports the hixie-76 version of the protocol.
package main
import (
"bufio"
"code.google.com/p/go.net/websocket"
"github.com/garyburd/redigo/redis"
//"github.com/davecgh/go-spew/spew"
"crypto/md5"
"encoding/hex"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
)
const PS = string(os.PathSeparator)
const PH = "/"
var (
pwd, _ = os.Getwd()
JSON = websocket.JSON
Message = websocket.Message
ActiveClients = make(map[ClientConn]int64)
redis_host string
rdPool *redis.Pool
Upload_Dir string
)
type ClientConn struct {
websocket *websocket.Conn
clientIP string
}
func init() {
f, err := os.Open("config")
if err != nil {
panic(err)
} else {
defer f.Close()
}
buf := bufio.NewReader(f)
line, err := buf.ReadString('\n')
if err != nil || io.EOF == err {
panic(err)
} else {
redis_host = strings.TrimSpace(line)
rdPool = initRedis(redis_host)
}
line, err = buf.ReadString('\n')
if err != nil || io.EOF == err {
panic(err)
} else {
Upload_Dir = strings.TrimSpace(line)
}
}
func SockServer(ws *websocket.Conn) {
var err error
var clientMessage string
var serverMessage string
defer func() {
if err = ws.Close(); err != nil {
pp("Websocket could not be closed", err.Error())
}
}()
client := ws.Request().RemoteAddr
pp("Client connected:", client)
sockClient := ClientConn{ws, client}
ActiveClients[sockClient] = time.Now().Unix()
pp("Number of clients connected:", len(ActiveClients))
for {
err = Message.Receive(ws, &clientMessage)
if err != nil {
pp("Websocket Disconnected waiting", err.Error())
delete(ActiveClients, sockClient)
pp("Number of clients still connected:", len(ActiveClients))
clientMessage = ""
return
} else {
if clientMessage == "GET" {
ret, err := redis.Strings(RedisExec(rdPool.Get(), "BLPOP", "screenshot:queue", 30))
if len(ret) == 2 && err == nil {
url := ret[1]
h := md5.New()
h.Write([]byte(url))
name := hex.EncodeToString(h.Sum(nil))
subDir := strconv.Itoa(time.Now().Year()) + PS + strconv.Itoa(int(time.Now().Month()))
os.MkdirAll(Upload_Dir+subDir, 0777)
filename_full := Upload_Dir + subDir + PS + name
serverMessage = filename_full + "|" + url
pp("pop queue ok.", client, serverMessage)
if err = Message.Send(ws, serverMessage); err != nil {
pp("Could not send message to ", client, err.Error())
}
} else {
p("pop queue error.", client, err.Error())
if err = Message.Send(ws, "NULL"); err != nil {
pp("Could not send message to ", client, err.Error())
}
}
} else if clientMessage == "OPEN" {
if err = Message.Send(ws, "OPEN"); err != nil {
pp("Could not send message to ", client, err.Error())
}
} else {
//todo
}
clientMessage = ""
}
}
}
func main() {
http.Handle("/socket", websocket.Handler(SockServer))
err := http.ListenAndServe("127.0.0.1:9527", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
phantomjs起多进程的,做一个服务器端screenshot的service非常简单,关键部分代码如下:
var page = require('webpage').create(),
system = require('system'),
address, output, size;
var loop = function() {
var ws = new WebSocket("ws://127.0.0.1:9527/socket");
ws.onopen = function(evt){
ws.send('OPEN');
//ws.send('GET');
console.log("Opened.");
};
ws.onclose = function(evt){
console.log("Closed.");
window.setTimeout(loop, 60000);
};
ws.onmessage = function(evt){
console.log("Message:"+ evt.data);
//ws.send(evt.data);
if(evt.data!= "" && evt.data!= "OPEN"){
arr= evt.data.split('|');
if (arr.length== 2){
name= arr[0]+ ".png";
url= arr[1];
screenshot(url, name, "");
}
}
ws.send('GET');
};
ws.onerror = function(evt){
console.log("Error." + evt.data);
};
};