取り敢えず、週末の成果(ちゃんと動くものではないので、そのまま使うことはお勧めしません)
"client1.go"の内容
package main
import (
"flag"
"log"
"net/url"
"github.com/gorilla/websocket"
)
// GetLoc GetLoc
type GetLoc struct {
ID int `json:"id"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
//Address string `json:"address"`
}
var addr = flag.String("addr", "0.0.0.0:8080", "http service address") // テスト
//var addr = flag.String("addr", "localhost:8080", "http service address") // テスト
var upgrader = websocket.Upgrader{} // use default options
func main() {
flag.Parse()
log.SetFlags(0)
u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo2"}
log.Printf("connecting to %s", u.String())
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
gl := GetLoc{
ID: 1,
Lat: 35.653976,
Lng: 139.796841,
}
log.Printf("ID:%d", gl.ID)
log.Printf("Lat:%f", gl.Lat)
log.Printf("Lng:%f", gl.Lng)
//err = c.WriteJSON(mt, gl)
err = c.WriteJSON(gl)
if err != nil {
log.Println("write:", err)
}
}
"server8.go"の内容
/*
// server7.go
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// 使い方
// go run server7.go (適当なシェルから)
// http://localhost:8080 (ブラウザ起動)
*/
package main
import (
"flag"
"html/template"
"log"
"net/http"
"github.com/gorilla/websocket"
)
// GetLoc GetLoc
type GetLoc struct {
ID int `json:"id"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
//Address string `json:"address"`
}
//var addr = flag.String("addr", "localhost:8080", "http service address")
var addr = flag.String("addr", "0.0.0.0:8080", "http service address") // テスト
var upgrader = websocket.Upgrader{} // use default options
func echo2(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
if err != nil {
log.Print("upgrade:", err)
return
}
defer c.Close()
for {
//mt, message, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
//_, _, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
gl := new(GetLoc)
err := c.ReadJSON(&gl) // クライアントからのメッセージの受信(mtはクライアント識別子)
log.Printf("ID:%d", gl.ID)
log.Printf("Lat:%f", gl.Lat)
log.Printf("Lng:%f", gl.Lng)
if err != nil {
log.Println("read:", err)
break
}
}
}
func echo(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
if err != nil {
log.Print("upgrade:", err)
return
}
defer c.Close()
/*
for {
//mt, message, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
_, _, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
if err != nil {
log.Println("read:", err)
break
}
// JSON(位置情報)を無理やり入れてみた
gl := GetLoc{
ID: 1,
Lat: 35.653976,
Lng: 139.796842,
}
//log.Printf("recv_serv: %s", gl)
//err = c.WriteJSON(mt, gl)
err = c.WriteJSON(gl)
if err != nil {
log.Println("write:", err)
break
}
}
*/
gl := GetLoc{
ID: 1,
Lat: 35.653976,
Lng: 139.796842,
}
//log.Printf("recv_serv: %s", gl)
//err = c.WriteJSON(mt, gl)
err = c.WriteJSON(gl)
if err != nil {
log.Println("write:", err)
}
}
func home(w http.ResponseWriter, r *http.Request) {
homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
}
func main() {
flag.Parse()
log.SetFlags(0)
http.HandleFunc("/echo2", echo2) // echo関数を登録 (サーバとして必要)
http.HandleFunc("/echo", echo) // echo関数を登録 (サーバとして必要)
http.HandleFunc("/", home) // home関数を登録
log.Fatal(http.ListenAndServe(*addr, nil)) // localhost:8080で起動をセット
}
var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>PruneCluster - Realworld 50k</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.js"></script>
<script src="http://kobore.net/PruneCluster.js"></script> <!-- これ、いずれローカルホストから取れるように換える -->
<link rel="stylesheet" href="http://kobore.net/examples.css"/> <!-- これも、いずれローカルホストから取れるように換える -->
<!-- goのテンプレートのローカルって、どこになるんだろう? -->
</head>
<body>
<div id="map"></div>
<script>
ws = new WebSocket("{{.}}"); // websocketの確立
/*
var print = function(message) {
var d = document.createElement("div");
d.textContent = message;
output.appendChild(d);
};
*/
//引数にはミリ秒を指定。(例:5秒の場合は5000)
function sleep(a){
var dt1 = new Date().getTime();
var dt2 = new Date().getTime();
while (dt2 < dt1 + a){
dt2 = new Date().getTime();
}
return;
}
var map = L.map("map", {
attributionControl: false,
zoomControl: false
}).setView(new L.LatLng(35.654543, 139.795534), 18);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
detectRetina: true,
maxNativeZoom: 18
}).addTo(map);
var leafletView = new PruneClusterForLeaflet(1,1); // (120,20)がデフォルト
/*
// 送信5発(3秒単位)を送信
ws.onopen = function (event) {
for (let i = 0; i < 1; i++){
ws.send("Ebata is great");
//print("send: Ebata is great");
//print("Start sleep");
sleep(1000);
//print("End sleep");
}
}
*/
var markers = [];
// 受信すると、勝手にここに飛んでくる
ws.onmessage = function (event) {
// データをJSON形式に変更
var obj = JSON.parse(event.data);
// データをマーカーとして登録
var marker = new PruneCluster.Marker(obj.lat, obj.lng);
markers.push(marker);
leafletView.RegisterMarker(marker);
// leafletView.ProcessView(); // 変更が行われたときに呼び出されなければなりません。
}
/*
// 100人分を登録する
var size = 1;
var markers = [];
for (var i = 0; i < size; ++i) {
var marker = new PruneCluster.Marker(35.654543 + (Math.random() - 0.5) * 0.00001 * size, 139.795534 + (Math.random() - 0.5) * 0.00002 * size);
markers.push(marker);
leafletView.RegisterMarker(marker);
}
*/
// ランダムウォークさせる
window.setInterval(function () {
for (i = 0; i < 1; ++i) {
//var coef = i < size / 8 ? 10 : 1;
var coef = 10;
var ll = markers[i].position;
ll.lat += (Math.random() - 0.5) * 0.00001 * coef;
ll.lng += (Math.random() - 0.5) * 0.00002 * coef;
}
leafletView.ProcessView(); // 変更が行われたときに呼び出されれなければならない
}, 500);
// サーバを止めると、ここに飛んでくる
ws.onclose = function(event) {
//print("CLOSE");
ws = null;
}
map.addLayer(leafletView);
</script>
</body>
</html>
`))