示例#1
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	server.SetTimeout(time.Second)
	server.Listen(":7777")

	cli := gomsg.NewClient()
	cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1]=%s", reverse(m)), nil
	})
	cli.Connect("localhost:7777")

	cli2 := gomsg.NewClient()
	cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[2]=%s", reverse(m)), nil
	})
	cli2.Connect("localhost:7777")

	time.Sleep(time.Millisecond * 100)
	// Warning: when requesting many in a server, the last response (end mark) will have a null connection
	server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) {
		fmt.Println("===> reply:", r, ", last?", ctx.Last())
	}, time.Second)

	time.Sleep(time.Second * 2)
	fmt.Println("I: close...")
	cli.Destroy()
	time.Sleep(time.Second * 5)
}
示例#2
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	server.Listen(":7777")

	ungrouped := 0
	cli := gomsg.NewClient()
	cli.Handle("HELLO", func(m string) {
		fmt.Println("<=== [0] processing:", m)
		ungrouped++
	})
	<-cli.Connect("localhost:7777")

	group1 := 0
	// Group HA subscriber
	cli1 := gomsg.NewClient()
	cli1.SetGroupId("HA")
	cli1.Handle("HELLO", func(m string) {
		fmt.Println("<=== [1] processing:", m)
		group1++
	})
	<-cli1.Connect("localhost:7777")

	// Group HA subscriber
	group2 := 0
	cli2 := gomsg.NewClient()
	cli2.SetGroupId("HA")
	cli2.Handle("HELLO", func(m string) {
		fmt.Println("<=== [2] processing:", m)
		group2++
	})
	<-cli2.Connect("localhost:7777")

	// Only one element of the group HA will process each message, alternately (round robin).
	server.Publish("HELLO", "one")
	wait()
	server.Publish("HELLO", "two")
	wait()
	server.Publish("HELLO", "three")
	wait()
	server.Publish("HELLO", "four")
	wait()

	if ungrouped != 4 {
		fmt.Println("ERROR: RECEIVED", ungrouped, "UNGROUPED EVENTS. EXPECTED 4.")
	}
	if group1 != 2 {
		fmt.Println("ERROR: RECEIVED", group1, "GROUP EVENTS. EXPECTED 2.")
	}
	if group2 != 2 {
		fmt.Println("ERROR: RECEIVED", group2, "GROUP EVENTS. EXPECTED 2.")
	}
	wait()
	server.Destroy()
	wait()
}
示例#3
0
文件: main.go 项目: jmptrader/gomsg
func main() {
	server := gomsg.NewServer()
	server.Listen(SERVER_PORT_1)
	defer server.Destroy()

	// client #1
	var received1 = 0
	cli1 := gomsg.NewClient()
	cli1.Handle(CONSUMER, func(m string) {
		fmt.Println("<<< client #1: received", m)
		if m == MESSAGE {
			received1++
		}
	})
	cli1.Connect(SERVER_1)
	defer cli1.Destroy()

	// client #2
	var received2 = 0
	cli2 := gomsg.NewClient()
	cli2.Handle(CONSUMER, func(m string) {
		fmt.Println("<<< client #2: received", m)
		if m == MESSAGE {
			received2++
		}
	})
	cli2.Connect(SERVER_1)
	defer cli2.Destroy()

	// give time to connect
	wait()

	// only one client will receive the message
	e := <-server.Push(CONSUMER, MESSAGE)
	if e != nil {
		fmt.Printf("Error: %s\n", e)
	}

	// a different client from before (round-robin)
	// will receive the message
	e = <-server.Push(CONSUMER, MESSAGE)
	if e != nil {
		fmt.Printf("Error: %s\n", e)
	}

	if received1 != 1 {
		fmt.Printf("Expected '%v', got '%v'\n", 1, received1)
	}

	if received2 != 1 {
		fmt.Printf("Expected '%v', got '%v'\n", 1, received2)
	}
}
示例#4
0
文件: main.go 项目: quintans/gomsg
func main() {
	// routing requests between server 1 and server 2
	server1 := gomsg.NewServer()
	server1.SetTimeout(time.Second)
	server1.Listen(":7777")
	server2 := gomsg.NewServer()
	server2.SetTimeout(time.Second)
	server2.Listen(":7778")
	// all (*) messages arriving to server 1 are routed to server 2
	gomsg.Route("*", server1, server2, time.Second,
		func(ctx *gomsg.Request) bool {
			fmt.Println("===>routing incoming msg:", string(ctx.Request()))
			return true
		},
		nil)

	// client 1 connects to server 1
	cli := gomsg.NewClient()
	cli.Connect("localhost:7777")

	cli2 := gomsg.NewClient()
	cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		if m != MESSAGE {
			fmt.Printf("###> EXPECTED '%s'. RECEIVED '%s'.\n", MESSAGE, m)
		}
		fmt.Println("<=== processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("Hello %s", m), nil
	})
	// client 2 connects to server 2
	cli2.Connect("localhost:7778")

	var err error
	/*
		err = <-cli.Push("XPTO", "PUSH: One")
		if err != nil {
			fmt.Println("W: error:", err)
		}
	*/
	err = <-cli.Request("HELLO", MESSAGE, func(ctx gomsg.Response, r string, e error) {
		if r != REPLY {
			fmt.Printf("###> EXPECTED '%s'. RECEIVED '%s'.\n", REPLY, r)
		}
		fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr())
	})
	if err != nil {
		fmt.Println("===> error:", err)
	}

	time.Sleep(time.Second * 3)
	cli.Destroy()
	time.Sleep(time.Millisecond * 100)
}
示例#5
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	server.Listen(":7777")
	cli := gomsg.NewClient()
	cli.Connect("localhost:7777")

	// this late server handler must propagate to the client
	server.Handle("XPTO", func(m string) {
		fmt.Println("<=== handling pull:", m)
	})
	time.Sleep(time.Millisecond * 100)

	e := <-cli.Publish("XPTO", "teste")
	if e != nil {
		fmt.Println("===> XPTO error:", e)
	}

	// this late client handler must propagate to the server
	cli.Handle("SUB", func(m string) {
		fmt.Println("<=== handling pub-sub:", m)
	})
	time.Sleep(time.Millisecond * 100)

	e = <-server.Publish("SUB", "teste")
	if e != nil {
		fmt.Println("===> SUB error:", e)
	}

	time.Sleep(time.Millisecond * 100)
}
示例#6
0
func (node *Node) connectPeer(peerAddr string) error {
	node.mu.Lock()
	defer node.mu.Unlock()

	if node.peers[peerAddr] == nil {
		cli := gomsg.NewClient().SetCodec(node.Codec)

		cli.OnConnect = func(w *gomsg.Wired) {
			node.Put(w.Conn(), w.Wire())
		}
		cli.OnClose = func(c net.Conn) {
			node.Kill(c)

			node.mu.Lock()
			defer node.mu.Unlock()
			// remove from connected peers
			delete(node.peers, peerAddr)
		}

		// doesn't try to reconnect
		cli.SetReconnectInterval(0)

		// wait for the connection to establish
		var err = <-cli.Connect(peerAddr)
		if err != nil {
			return err
		}
		node.peers[peerAddr] = cli
	}
	return nil
}
示例#7
0
文件: main.go 项目: jmptrader/gomsg
func main() {
	cli := gomsg.NewClient().Connect("localhost:7777")
	time.Sleep(time.Millisecond * 100)

	// THE SERVER SHOWS UP AFTER THE CLIENT
	server := gomsg.NewServer()
	server.Handle("XPTO", func(m string) {
		fmt.Println("<=== handling pull:", m)
	})
	server.Listen(":7777")
	time.Sleep(time.Second)

	e := <-cli.Publish("XPTO", "teste")
	if e != nil {
		fmt.Println("===> error:", e)
	}

	/*
		cli.Handle("SUB", func(m string) {
			fmt.Println("<=== handling pub-sub:", m)
		})
		time.Sleep(time.Millisecond * 100)

		<-server.Publish("SUB", "teste")
	*/
	time.Sleep(time.Second)
}
示例#8
0
文件: bstar.go 项目: quintans/gomsg
func NewBStarClient(primary string, backup string) BStarClient {
	this := BStarClient{
		client:  gomsg.NewClient().SetCodec(codec),
		servers: []string{primary, backup},
	}
	this.client.SetTimeout(time.Second)
	this.client.Connect(primary)

	return this
}
示例#9
0
func NewPeer(dirAddr string, bindAddr string, codec gomsg.Codec) *Peer {
	this := &Peer{
		codec: codec,
		peers: NewPeers(),
	}
	this.local = gomsg.NewServer()
	this.local.SetTimeout(time.Second)
	this.local.SetCodec(codec)
	this.local.Listen(bindAddr)

	this.dir = gomsg.NewClient().SetCodec(codec)
	this.dir.SetTimeout(time.Second)
	this.dir.OnConnect = func(w *gomsg.Wired) {
		this.dir.Handle("NEW", func(peerAddr string) {
			if peerAddr != this.self {
				fmt.Println("====>", bindAddr, ": new peer at", peerAddr)
				cli := gomsg.NewClient().SetCodec(codec)
				cli.Connect(peerAddr)
				this.peers.Put(peerAddr, cli)
			}
		})
		this.dir.Handle("DROP", func(peerAddr string) {
			this.peers.Remove(peerAddr)
		})

		port := this.local.Port()
		<-this.dir.Request("DIR", nil, func(ctx gomsg.Response, addrs []string) {
			this.self = fmt.Sprint(ctx.Connection().LocalAddr().(*net.TCPAddr).IP, ":", port)
			for _, v := range addrs {
				cli := gomsg.NewClient().SetCodec(this.codec)
				cli.Connect(v)
				this.peers.Put(v, cli)
			}
		})
		this.dir.Push("READY", port)
	}
	this.dir.Connect(dirAddr)

	return this
}
示例#10
0
文件: bstar.go 项目: quintans/gomsg
//  This is our main task. First we bind/connect our sockets with our
//  peer and make sure we will get state messages correctly. We use
//  three sockets; one to publish state, one to subscribe to state, and
//  one for client requests/replies:
func NewBStar(primary bool, frontentAddr string, stateLocalAddr string, stateRemoteAddr string) *BStar {
	this := &BStar{}
	if primary {
		fmt.Println("I: Primary active, waiting for backup (passive)")
		this.state = STATE_PRIMARY
	} else {
		fmt.Println("I: Backup passive, waiting for primary (active)")
		this.state = STATE_BACKUP
	}

	this.quit = make(chan bool, 1)

	this.statepub = gomsg.NewClient().SetCodec(codec)

	this.statesub = gomsg.NewServer()
	this.statesub.SetCodec(codec)
	this.statesub.Handle("STATE", func(ctx *gomsg.Request) {
		state, _ := ctx.Reader().ReadUI8()
		//  Have state from our peer, execute as event
		if this.stateMachine(Event(state)) {
			this.quit <- true //  Error, so exit
		} else {
			this.updatePeerExpiry()
		}

	})

	this.frontend = gomsg.NewServer()
	this.frontend.SetCodec(codec)
	this.frontend.Handle("*", func(ctx *gomsg.Request) {
		//  Have a client request
		ok := !this.stateMachine(CLIENT_REQUEST)
		if ok {
			this.frontendHandler(this, ctx)
		} else {
			// rejects request
			ctx.Terminate()
		}
	})

	this.stateRemoteAddr = stateRemoteAddr
	this.stateLocalAddr = stateLocalAddr
	this.frontentAddr = frontentAddr

	return this
}
示例#11
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	server.SetTimeout(time.Second)
	server.Listen(":7777")

	cli := gomsg.NewClient()
	cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1]=%s", reverse(m)), nil
	})
	cli.Connect("localhost:7777")

	/*
		cli2 := gomsg.NewClient()
		cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
			fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr())
			return fmt.Sprintf("[2]=%s", reverse(m)), nil
		})
		cli2.Connect("localhost:7777")

		// just to get in the way
		cli3 := gomsg.NewClient()
		cli3.Connect("localhost:7777")
	*/

	// ===============

	//time.Sleep(time.Millisecond * 100)
	fmt.Println("====> requesting...")
	<-server.Request("REVERSE", "hello", func(ctx gomsg.Response, r string) {
		fmt.Println("===> reply:", r)
	})
	/*
		server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) {
			fmt.Println("===> reply:", ctx.Kind, r)
		}, time.Second)
	*/

	time.Sleep(time.Second * 2)
	fmt.Println("I: close...")
	cli.Destroy()
	time.Sleep(time.Second * 5)
}
示例#12
0
文件: bstar.go 项目: quintans/gomsg
// Request sends a request to the Binary Star.
// If there's no reply within our timeout, we close the socket and try again.
// In Binary Star, it's the client vote that decides which
// server is primary; the client must therefore try to connect
// to each server in turn:
func (bsc BStarClient) Request(name string, payload interface{}, handler interface{}, timeout time.Duration) {
	expectReply := true
	// A request is used so that the bstar server can decide not to reply
	// if there is an inconsistent server state
	ch := bsc.client.RequestTimeout(name, payload, handler, timeout)
	for expectReply {
		err := <-ch
		if err == nil {
			expectReply = false
		} else {
			fmt.Println("W: no response from server, failing over. error:", err)
			//  client is confused; close it and open a new one
			bsc.client.Destroy()
			bsc.serverNbr = (bsc.serverNbr + 1) % 2
			<-time.After(SETTLE_DELAY)
			fmt.Printf("I: connecting to server at %s...\n", bsc.servers[bsc.serverNbr])
			bsc.client = gomsg.NewClient().SetCodec(codec)
			bsc.client.Connect(bsc.servers[bsc.serverNbr])

			//  Send request again, on new client
			ch = bsc.client.RequestTimeout(name, payload, handler, timeout)
		}
	}
}
示例#13
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	server.SetTimeout(time.Second)
	server.Listen(":7777")

	cli := gomsg.NewClient()
	cli2 := gomsg.NewClient()

	fmt.Println("=========== STICKY PUSH =============")

	cli.Handle("PUSHING", func(ctx *gomsg.Request, m string) {
		fmt.Println("<=== processing PUSHING (1):", m, "from", ctx.Connection().RemoteAddr())
	})
	cli.Handle("NOISE", func(ctx *gomsg.Request, m string) {
		fmt.Println("<=== processing NOISE (21):", m, "from", ctx.Connection().RemoteAddr())
	})

	cli2.Handle("PUSHING", func(ctx *gomsg.Request, m string) {
		fmt.Println("<=== processing PUSHING (2):", m, "from", ctx.Connection().RemoteAddr())
	})
	cli2.Handle("NOISE", func(ctx *gomsg.Request, m string) {
		fmt.Println("<=== processing NOISE (22):", m, "from", ctx.Connection().RemoteAddr())
	})

	cli.Connect("localhost:7777")
	cli2.Connect("localhost:7777")

	wait()

	// note the FILTER_TOKEN at the end. This way we can define a range of Stickyness
	server.Stick("PUSH"+gomsg.FILTER_TOKEN, time.Millisecond*500)

	server.Push("PUSHING", "ping")
	wait()
	server.Push("PUSHING", "ping")
	wait()

	server.Push("NOISE", "---noise--- will provoque the rotation of the general cursor")
	wait()
	server.Push("PUSHING", "ping")
	wait()
	server.Push("NOISE", "---noise--- will provoque the rotation of the general cursor")
	wait()
	server.Push("PUSHING", "ping")
	time.Sleep(time.Second)
	server.Push("PUSHING", "change wire")
	wait()

	fmt.Println("=========== STICKY REQUEST =============")

	cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing REVERSE (1):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1]=%s", reverse(m)), nil
	})
	cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing REVERSE (2):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[2]=%s", reverse(m)), nil
	})
	wait()

	server.Stick("REVERSE", time.Millisecond*500)
	// Warning: when requesting many in a server, the last response (end mark) will have a null connection
	var resultFn = func(ctx gomsg.Response, r string) {
		fmt.Println("===> reply:", r, ", last?", ctx.Last())
	}
	server.Request("REVERSE", "hello", resultFn)
	wait()
	server.Request("REVERSE", "world", resultFn)
	wait()
	server.Request("REVERSE", "ola", resultFn)
	wait()
	server.Request("REVERSE", "mundo", resultFn)
	time.Sleep(time.Second)
	server.Request("REVERSE", "change wire", resultFn)
	wait()

	time.Sleep(time.Second * 2)

	fmt.Println("I: close...")
	cli.Destroy()
	time.Sleep(time.Second * 5)
}
示例#14
0
文件: main.go 项目: jmptrader/gomsg
func main() {
	server := gomsg.NewServer()
	server.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("Hello %s", m), nil
	})
	server.Handle("XPTO", func(m string) {
		fmt.Println("<=== handling pull:", m)
	})
	server.Listen(":7777")

	cli := gomsg.NewClient()
	cli.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing (1):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1]=%s", reverse(m)), nil
	})
	cli.Handle("SUB", func(m string) {
		fmt.Println("<=== handling pub-sub:", m)
	})
	cli.Connect("localhost:7777")

	cli2 := gomsg.NewClient()
	cli2.Handle("REVERSE", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== processing (2):", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[2]=%s", reverse(m)), nil
	})
	cli2.Handle("SUB", func(m string) {
		fmt.Println("<=== handling pub-sub:", m)
	})
	cli2.Connect("localhost:7777")

	//var err error
	/*
		messages := []string{"Hello", "World", "Paulo"}
		for _, m := range messages {
			err = <-cli.Request("HELLO", m, func(ctx gomsg.IResponse, r string) {
				fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr())
			})
			if err != nil {
				fmt.Println("===> error:", err)
			}
		}
	*/

	time.Sleep(time.Millisecond * 100)
	// Warning: when requesting many in a server, the last response (end mark) will have a null connection
	server.RequestAll("REVERSE", "hello", func(ctx gomsg.Response, r string) {
		fmt.Println("===> reply:", r)
	}, time.Second)
	/*
		server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) {
			fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr())
		})
		server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) {
			fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr())
		})
		server.Request("REVERSE", "hello", func(ctx gomsg.IResponse, r string) {
			fmt.Println("===> reply:", r, "from", ctx.Connection().RemoteAddr())
		})
	*/

	//server.Publish("SUB", "PUB: La")
	/*
		err = <-cli.Publish("XPTO", "PUB: La")
		err = <-cli.Publish("XPTO", "PUB: Vida")
		err = <-cli.Publish("XPTO", "PUB: Loca")
	*/

	//cli.Push("XPTO", "One")

	/*
		err = <-cli.Push("XPTO", "PUSH: Two")
		err = <-cli.Push("XPTO", "PUSH: Three")
		err = <-cli.Push("XPTO", "PUSH: Four")
		time.Sleep(time.Millisecond * 100)

		err = <-cli.Push("FAIL", 123)
		fmt.Println("I: error:", err)
		if err == nil {
			fmt.Println("E: Should have returned an error")
		}
	*/

	time.Sleep(time.Millisecond * 100)
	fmt.Println("I: close...")
	cli.Destroy()
	time.Sleep(time.Millisecond * 100)
}
示例#15
0
文件: main.go 项目: quintans/gomsg
func main() {
	// all messages arriving to the server are routed to the clients
	server := gomsg.NewServer()
	server.Listen(":7777")
	server.Route("*", time.Second, nil, nil)

	cli := gomsg.NewClient()
	cli.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== [1] processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1] Hello %s", m), nil
	})
	// sends multi reply
	cli.Handle("PIPE", func(ctx *gomsg.Request) {
		ctx.SendReply([]byte("\"Pipe #1\""))
		ctx.SendReply([]byte("\"Pipe #2\""))
		ctx.Terminate()
	})
	cli.Connect("localhost:7777")

	// just to get in the way
	cli3 := gomsg.NewClient()
	cli3.Connect("localhost:7777")

	cli2 := gomsg.NewClient()
	cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== [2] processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[2] Hello %s", m), nil
	})
	cli2.Handle("PIPE", func(ctx *gomsg.Request) string {
		return "Pipe #201"
	})
	cli2.Connect("localhost:7777")

	<-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) {
		fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr())
	})
	fmt.Println("===============")
	<-cli3.RequestAll("PIPE", nil, func(ctx gomsg.Response, s string) {
		fmt.Println("===PIPE===> reply:", ctx.Kind, string(ctx.Reply()), s)
	})
	fmt.Println("===============")
	<-cli3.Request("PIPE", nil, func(ctx gomsg.Response, s string) {
		fmt.Println("===PIPE===> reply:", ctx.Kind, string(ctx.Reply()), s)
	})
	/*
		cli.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) {
			fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr())
		})

		// check to see if the server is working
		server.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) {
			fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr())
		})
		server.Request("HELLO", "World!", func(ctx gomsg.IResponse, r string, e error) {
			fmt.Println("=================> reply:", r, e, "from", ctx.Connection().RemoteAddr())
		})
	*/

	time.Sleep(time.Millisecond * 100)
	cli.Destroy()
	time.Sleep(time.Millisecond * 100)
}
示例#16
0
文件: main.go 项目: quintans/gomsg
func main() {
	server := gomsg.NewServer()
	// keep alive
	var timeout = gomsg.NewTimeout(CLEAN_CYCLE, time.Second, func(o interface{}) {
		c := o.(net.Conn)
		fmt.Println("=====> killing connection from", c.RemoteAddr())
		server.Wires.Kill(c)
	})

	server.OnConnect = func(w *gomsg.Wired) {
		// starts monitoring
		timeout.Delay(w.Conn())
	}
	// for PING messages the server will reply immediatly,
	// without relaying the message to the clients.
	server.Route("*", time.Second,
		func(ctx *gomsg.Request) bool {
			// any message received, delays the timeout
			timeout.Delay(ctx.Connection())

			if ctx.Name == "PING" {
				ctx.SetReply([]byte("PONG"))
				return false
			}

			return true
		},
		nil)

	server.Listen(":7777")

	cli := gomsg.NewClient()
	cli.SetReconnectInterval(0)
	cli.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== [1] processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[1] Hello %s", m), nil
	})
	cli.Connect("localhost:7777")

	// just to get in the way
	cli3 := gomsg.NewClient()
	cli3.SetReconnectInterval(0)
	cli3.Connect("localhost:7777")

	cli2 := gomsg.NewClient()
	cli2.SetReconnectInterval(0)
	cli2.Handle("HELLO", func(ctx *gomsg.Request, m string) (string, error) {
		fmt.Println("<=== [2] processing:", m, "from", ctx.Connection().RemoteAddr())
		return fmt.Sprintf("[2] Hello %s", m), nil
	})
	cli2.Connect("localhost:7777")

	<-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) {
		fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr())
	})

	time.Sleep(time.Millisecond * 2000)
	<-cli3.RequestAll("HELLO", "World!", func(ctx gomsg.Response, r string, e error) {
		fmt.Println("===HELLO===> reply:", r, e, "from", ctx.Connection().RemoteAddr())
	})

	time.Sleep(time.Millisecond * 1000)
}
示例#17
0
文件: main.go 项目: quintans/gomsg
func main() {
	// all messages arriving to the server are routed to the clients
	server := gomsg.NewServer()
	server.Listen(":7777")
	server.Route("*", time.Second, nil, nil)

	ungrouped := 0
	cli := gomsg.NewClient()
	cli.Handle("HELLO", func(m string) {
		fmt.Println("<=== [0] processing:", m)
		ungrouped++
	})
	<-cli.Connect("localhost:7777")

	group1 := 0
	// Group HA subscriber
	cli1 := gomsg.NewClient()
	cli1.SetGroupId("HA")
	cli1.Handle("HELLO", func(m string) {
		fmt.Println("<=== [1] processing:", m)
		group1++
	})
	<-cli1.Connect("localhost:7777")

	// Group HA subscriber
	group2 := 0
	cli2 := gomsg.NewClient()
	cli2.SetGroupId("HA")
	cli2.Handle("HELLO", func(m string) {
		fmt.Println("<=== [2] processing:", m)
		group2++
	})
	<-cli2.Connect("localhost:7777")

	// publisher
	cli3 := gomsg.NewClient()
	<-cli3.Connect("localhost:7777")

	// Only one element of the group HA will process each message, alternately (round robin).
	//	cli3.Publish("HELLO", "Hello World!")
	//	cli3.Publish("HELLO", "Olá Mundo!")
	//	cli3.Publish("HELLO", "YESSSS!")
	cli3.Publish("HELLO", "one")
	wait()
	cli3.Publish("HELLO", "two")
	wait()
	cli3.Publish("HELLO", "three")
	wait()
	cli3.Publish("HELLO", "four")
	wait()

	if ungrouped != 4 {
		fmt.Println("ERROR: RECEIVED", ungrouped, "UNGROUPED EVENTS. EXPECTED 4.")
	}
	if group1 != 2 {
		fmt.Println("ERROR: RECEIVED", group1, "GROUP EVENTS. EXPECTED 2.")
	}
	if group2 != 2 {
		fmt.Println("ERROR: RECEIVED", group2, "GROUP EVENTS. EXPECTED 2.")
	}
	wait()
	cli.Destroy()
	wait()
}
示例#18
0
// Connect binds a to a local address to provide services
// and connect to the directory remove addresses
func (node *Node) Connect(bindAddr string, dirAddrs ...string) error {
	var err = node.local.Listen(bindAddr)
	if err != nil {
		return err
	}

	node.remoteDirs = make([]*gomsg.Client, len(dirAddrs))

	for k, dirAddr := range dirAddrs {
		var dir = gomsg.NewClient()
		node.remoteDirs[k] = dir
		dir.Handle(C_PEERREADY, func(provider Provider) {
			fmt.Println("I: > node:", bindAddr, "C_PEERREADY notified of a new peer:", provider)

			node.mu.Lock()
			node.providers[provider.Endpoint] = &provider
			node.mu.Unlock()
		})
		dir.Handle(C_ADDSERVICE, func(service Service) {
			fmt.Println("I: > node:", bindAddr, "C_ADDSERVICE notified of a new service:", service)

			node.mu.Lock()
			for _, v := range node.providers {
				if v.Endpoint == service.Endpoint {
					v.AddService(service.Name)
					break
				}
			}
			node.mu.Unlock()
		})
		dir.Handle(C_CANCELSERVICE, func(service Service) {
			fmt.Println("I: > node:", bindAddr, "C_CANCELSERVICE notified of canceled service:", service)

			node.mu.Lock()
			var empty = false
			for _, v := range node.providers {
				if v.Endpoint == service.Endpoint {
					empty = v.RemoveService(service.Name)
					break
				}
			}
			node.mu.Unlock()

			if empty {
				node.disconnectPeer(service.Endpoint)
			}
		})
		dir.Handle(C_DROPPEER, func(endpoint string) {
			fmt.Println("I: > node:", bindAddr, "C_DROPPEER peer:", endpoint)

			node.mu.Lock()
			delete(node.providers, endpoint)
			node.mu.Unlock()

			node.disconnectPeer(endpoint)
		})

		dir.OnConnect = func(w *gomsg.Wired) {

			// this will ping the service directory,
			// and if there is no reply after some attempts it will reconnect
			go func() {
				var ticker = time.NewTicker(node.PingInterval)
				var retries = node.PingFailures
				for _ = range ticker.C {
					if dir.Active() {
						var pong = ""
						var err = <-dir.RequestTimeout(PING, nil, func(ctx gomsg.Response, reply string) {
							pong = reply
						}, time.Millisecond*10)

						if _, ok := err.(gomsg.TimeoutError); ok || pong != PONG {
							retries--
							fmt.Println("D: > PING failed. retries left:", retries)
							if retries == 0 {
								ticker.Stop()
							}
						} else {
							retries = node.PingFailures
						}
					} else {
						ticker.Stop()
					}
				}
				dir.Reconnect()
			}()

			node.dirs.Put(w.Conn(), w.Wire())

			// only want for the first established connection to get the list of providers
			if node.dirs.Size() > 1 {
				return
			}

			node.mu.RLock()
			var services = make([]string, len(node.provides))
			var i = 0
			for k := range node.provides {
				services[i] = k
				i++
			}
			node.mu.RUnlock()

			var provider = NewProvider(strconv.Itoa(node.local.BindPort()))
			provider.Services = services

			dir.Request(S_PEERREADY, provider, func(ctx gomsg.Response, providers []Provider) {
				node.mu.Lock()
				defer node.mu.Unlock()

				for _, v := range providers {
					node.providers[v.Endpoint] = &v
				}
			})
		}

		dir.OnClose = func(c net.Conn) {
			node.dirs.Kill(c)
			for k, v := range node.remoteDirs {
				if v.Connection() == c {
					// since the slice has a non-primitive, we have to zero it
					copy(node.remoteDirs[k:], node.remoteDirs[k+1:])
					node.remoteDirs[len(node.remoteDirs)-1] = nil // zero it
					node.remoteDirs = node.remoteDirs[:len(node.remoteDirs)-1]
				}
			}
		}

		dir.Connect(dirAddr)
	}

	return nil
}