wsarecv: An existing connection was forcibly closed by the remote host. がどうにも分からない
PruneMobile というソフトウェアを作っています。
クライアント側のプログラムで、Golang(Go言語)の 並列(通信)処理を始めて本格的に実装したのですが、サーバ側にエラーが乱発しています。
Golangの通信プログラムの仕様は今一つ分かなくて(C言語なら「私がマニュアルだ」と傲慢に言い放ちますが)、試行錯誤の最中です。
"Go"は"C"と、ポインタや配列も違って、勉強し直し状態です。
それはさておき、クライアント側のプログラムは、以下の通り。ポイントは、
go passenger(1)
go passenger(2)
go passenger(3)
go passenger(4)
でスレッド処理をしてみたところです。
// client6.go ペアは server12.go
package main
import (
"flag"
"log"
"net/url"
"os"
"github.com/gorilla/websocket"
"math/rand"
"time"
)
// GetLoc GetLoc
type GetLoc struct {
ID int `json:"id"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
//Address string `json:"address"`
}
var gl [100]GetLoc
var gl2 [100]GetLoc
var c [100](*websocket.Conn)
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 random(min, max float64) float64 {
return rand.Float64()*(max-min) + min
}
func main() {
rand.Seed(time.Now().UnixNano())
flag.Parse()
log.SetFlags(0)
go passenger(1)
go passenger(2)
go passenger(3)
go passenger(4)
time.Sleep(25 * time.Second)
}
func passenger(i int) {
/*
gl[i] = GetLoc{
ID: 0,
Lat: 35.653976,
Lng: 139.796821,
}
*/
u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo2"}
log.Printf("connecting to %s", u.String())
var err error
c[i], _, err = websocket.DefaultDialer.Dial(u.String(), nil)
//c[i] = cc
if err != nil {
log.Fatal("dial:", err)
}
defer c[i].Close()
gl[i].ID = 0
gl[i].Lat = 35.653976
gl[i].Lng = 139.796821
if i != -100 {
log.Printf("before1 %d ID:%d", i, gl[i].ID)
log.Printf("before1 %d Lat:%f", i, gl[i].Lat)
log.Printf("before1 %d Lng:%f", i, gl[i].Lng)
}
//err = c.WriteJSON(mt, gl)
err = c[i].WriteJSON(gl[i])
if err != nil {
log.Println("write:", err)
}
//&(gl2[i]) = new(GetLoc)
err = c[i].ReadJSON(&(gl2[i]))
if i != -100 {
log.Printf("after1 %d ID:%d", i, gl2[i].ID)
log.Printf("after1 %d Lat:%f", i, gl2[i].Lat)
log.Printf("after1 %d Lng:%f", i, gl2[i].Lng)
}
if gl2[i].ID == 0 {
// 強制停止
os.Exit(1)
}
gl[i].ID = gl2[i].ID
for k := 0; k < 20; k++ {
gl[i].Lat += random(0.5, -0.5) * 0.00001 * 10 * 5
gl[i].Lng += random(0.5, -0.5) * 0.00002 * 10 * 5
if i != -100 {
log.Printf("before2 %d ID:%d", i, gl[i].ID)
log.Printf("before2 %d Lat:%f", i, gl[i].Lat)
log.Printf("before2 %d Lng:%f", i, gl[i].Lng)
}
err = c[i].WriteJSON(gl[i])
if err != nil {
log.Println("write:", err)
}
//gl2[i] := new(GetLoc)
err = c[i].ReadJSON(&(gl2[i]))
if i != -100 {
log.Printf("after2 %d ID:%d", i, gl2[i].ID)
log.Printf("after2 %d Lat:%f", i, gl2[i].Lat)
log.Printf("after2 %d Lng:%f", i, gl2[i].Lng)
}
time.Sleep(1 * time.Second) // 1秒休む
}
gl[i].ID = gl2[i].ID
gl[i].Lat = 999.9
gl[i].Lng = 999.9
log.Printf("before3 %d ID:%d", i, gl[i].ID)
log.Printf("before3 %d Lat:%f", i, gl[i].Lat)
log.Printf("before3 %d Lng:%f", i, gl[i].Lng)
err = c[i].WriteJSON(gl[i])
err = c[i].ReadJSON(&(gl2[i]))
log.Printf("after3 %d ID:%d", i, gl2[i].ID)
log.Printf("after3 %d Lat:%f", i, gl2[i].Lat)
log.Printf("after3 %d Lng:%f", i, gl2[i].Lng)
}
でもって、サーバ側に、
wsarecv: An existing connection was forcibly closed by the remote host.
がでてくるのですが、これがどうにも分からない。
websocket.DefaultDialer.Dialもスレッド単位で分離しているから、良さそうなんだけどなー
サーバ側の出力コンソールは、こんな感じ
first ID:0
117 after gl = <-chan2_1
first Lat:0.000000
94
first Lng:0.000000
126
read: read tcp 127.0.0.1:8080->127.0.0.1:50368: wsarecv: An existing connection was forcibly closed by the remote host.
138
write: write tcp 127.0.0.1:8080->127.0.0.1:50366: wsasend: An existing connection was forcibly closed by the remote host.
after gl2.id = 3
after gl2.lat = 35.653909
after gl2.lng= 139.796333
145
148
113 before gl = <-chan2_1
86
final ID:3
final Lat:35.653909
final Lng:139.796333
94
write: write tcp 127.0.0.1:8080->127.0.0.1:50365: wsasend: An existing connection was forcibly closed by the remote host
とりあえず、忘れそうなので、自分の為にメモを残しておきます。
websocket.DefaultDialer.Dialもスレッド単位ごとに発行しているから分離しているから、良さそうなんだけどなぁ。Websocketの複数のエンドポイントを作って並列処理につっこむには、もう一頑張り必要、ということでしょう。
ちなみに「誰か、私を助けてくれたっていいんだからね!」と申し上げておきます。