Beispiel #1
0
// Connect to a STOMP broker, publish some messages and disconnect.
func main() {

	st := time.Now()

	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// *NOTE* application specific functionaltiy starts here!
	sh := stompngo.Headers{"destination", sngecomm.Dest()}
	ll.Printf("%stag:%s connsess:%s destination dest:%s\n",
		exampid, tag, conn.Session(),
		sngecomm.Dest())
	if senv.Persistent() {
		sh = sh.Add("persistent", "true")
	}
	ms := exampid + "message: "
	for i := 1; i <= senv.Nmsgs(); i++ {
		mse := ms + fmt.Sprintf("%d", i)
		ll.Printf("%stag:%s connsess:%s main_sending mse:~%s~\n",
			exampid, tag, conn.Session(),
			mse)
		e := conn.Send(sh, mse)
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
				exampid, tag, conn.Session(),
				e.Error()) // Handle this ......
		}
		ll.Printf("%stag:%s connsess:%s main_send_complete mse:~%s~\n",
			exampid, tag, conn.Session(),
			mse)
		time.Sleep(100 * time.Millisecond)
	}
	// *NOTE* application specific functionaltiy ends here!

	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_disconnect error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))
}
func ShowRunParms(exampid string) {
	llu.Printf("%sHOST:%v\n", exampid, os.Getenv("STOMP_HOST"))
	llu.Printf("%sPORT:%v\n", exampid, os.Getenv("STOMP_PORT"))
	llu.Printf("%sPROTOCOL:%v\n", exampid, senv.Protocol())
	llu.Printf("%sVHOST:%v\n", exampid, senv.Vhost())
	llu.Printf("%sNQS:%v\n", exampid, Nqs())
	llu.Printf("%sNMSGS:%v\n", exampid, senv.Nmsgs())
	llu.Printf("%sSUBCHANCAP:%v\n", exampid, senv.SubChanCap())
	llu.Printf("%sRECVFACT:%v\n", exampid, RecvFactor())
	llu.Printf("%sSENDFACT:%v\n", exampid, SendFactor())
	llu.Printf("%sRECVWAIT:%t\n", exampid, RecvWait())
	llu.Printf("%sSENDWAIT:%t\n", exampid, SendWait())
	llu.Printf("%sACKMODE:%v\n", exampid, AckMode())
}
/*
runSender sends all messages to a specified queue.
*/
func runSender(conn *stompngo.Connection, qns string) {
	ltag := tag + "-runsender"

	d := sngecomm.Dest() + "." + qns
	id := stompngo.Uuid() // A unique sender id
	ll.Printf("%stag:%s connsess:%s start id:%s dest:%s\n",
		exampid, ltag, conn.Session(),
		id, d)
	wh := stompngo.Headers{"destination", d, "senderId", id,
		"qnum", qns} // basic send Headers
	if senv.Persistent() {
		wh = wh.Add("persistent", "true")
	}
	tmr := time.NewTimer(100 * time.Hour)
	nmsgs := senv.Nmsgs()
	for mc := 1; mc <= nmsgs; mc++ {
		sh := append(wh, "msgnum", fmt.Sprintf("%d", mc))
		// Generate a message to send ...............
		ll.Printf("%stag:%s  connsess:%s send id:%s qns:%s mc:%d\n",
			exampid, ltag, conn.Session(),
			id, qns, mc)
		e := conn.Send(sh, string(sngecomm.Partial()))
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error qns:%v error:%v",
				exampid, ltag, conn.Session(),
				qns, e.Error()) // Handle this ......
		}
		if mc == nmsgs {
			break
		}
		if sw {
			dt := time.Duration(sngecomm.ValueBetween(min, max, sf))
			ll.Printf("%stag:%s connsess:%s send_stagger dt:%v qns:%s mc:%d\n",
				exampid, ltag, conn.Session(),
				dt, qns, mc)
			tmr.Reset(dt)
			_ = <-tmr.C
			runtime.Gosched()
		}
	}
	ll.Printf("%stag:%s connsess:%s end id:%s dest:%s\n",
		exampid, ltag, conn.Session(),
		id, d)
	//
	wgs.Done()
}
/*
	Start all sender go routines.
*/
func startSenders(nqs int) {
	ltag := tag + "-startsenders"

	ll.Printf("%stag:%s connsess:%s queue_count nqs:%v\n",
		exampid, ltag, conn.Session(),
		nqs)

	mc := senv.Nmsgs() // message count
	ll.Printf("%stag:%s connsess:%s message_count mc:%v\n",
		exampid, ltag, conn.Session(),
		mc)
	for i := 1; i <= nqs; i++ { // all queues
		wgs.Add(1)
		go sender(i, mc)
	}
	wgs.Wait()

	ll.Printf("%stag:%s connsess:%s ends nqs:%v mc:%v\n",
		exampid, ltag, conn.Session(),
		nqs, mc)
	wga.Done()
}
func startReceivers(qn int) {
	ltag := tag + "-startreceivers"

	ll.Printf("%stag:%s connsess:%s starts qn:%d\n",
		exampid, ltag, sngecomm.Lcs,
		qn)

	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, ltag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s on_connect error:%v",
			exampid, ltag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	nmsgs := senv.Nmsgs() // get message count
	ll.Printf("%stag:%s connsess:%s message_count nmsgs:%d qn:%d\n",
		exampid, ltag, conn.Session(),
		nmsgs, qn)
	for i := 1; i <= qn; i++ { // all queues
		wgr.Add(1)
		go receiver(conn, i, nmsgs)
	}
	ll.Printf("%stag:%s connsess:%s starts_done\n",
		exampid, ltag, conn.Session())
	wgr.Wait()

	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, ltag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s on_disconnect error:%v",
			exampid, ltag, conn.Session(),
			e.Error()) // Handle this ......
	}

	sngecomm.ShowStats(exampid, ltag, conn)
	wga.Done()
}
/*
runReceive receives all messages from a specified queue.
*/
func runReceive(conn *stompngo.Connection, q int, w *sync.WaitGroup) {
	ltag := tag + "-runreceive"

	qns := fmt.Sprintf("%d", q) // queue number
	id := stompngo.Uuid()       // A unique subscription ID
	d := sngecomm.Dest() + "." + qns

	ll.Printf("%stag:%s connsess:%s starts id:%s qns:%s d:%s\n",
		exampid, ltag, conn.Session(),
		id, qns, d)

	// Subscribe (use common helper)
	sc := sngecomm.HandleSubscribe(conn, d, id, sngecomm.AckMode())
	ll.Printf("%stag:%s connsess:%s subscribe_done id:%s qns:%s d:%s\n",
		exampid, ltag, conn.Session(),
		id, qns, d)

	//
	tmr := time.NewTimer(100 * time.Hour)

	pbc := sngecomm.Pbc() // Print byte count

	nmsgs := senv.Nmsgs()

	// Receive loop
	var md stompngo.MessageData
	for mc := 1; mc <= nmsgs; mc++ {
		ll.Printf("%stag:%s connsess:%s chanchek id:%s qns:%s lensc:%d capsc:%d\n",
			exampid, ltag, conn.Session(),
			id, qns, len(sc), cap(sc))
		select {
		case md = <-sc:
		case md = <-conn.MessageData:
			// Frames RECEIPT or ERROR not expected here
			ll.Fatalf("%stag:%s connsess:%s send_error qns:%v md:%v",
				exampid, ltag, conn.Session(),
				qns, md) // Handle this ......
		}

		if md.Error != nil {
			ll.Fatalf("%stag:%s connsess:%s receive_error qns:%v error:%v\n",
				exampid, ltag, conn.Session(),
				qns, md.Error)
		}

		// Process the inbound message .................
		ll.Printf("%stag:%s connsess:%s inbound id:%s qns:%s mc:%d\n",
			exampid, ltag, conn.Session(),
			id, qns, mc)
		// Sanity check the message Command, and the queue and message numbers
		mns := fmt.Sprintf("%d", mc) // string message number
		if md.Message.Command != stompngo.MESSAGE {
			ll.Fatalf("%stag:%s connsess:%s bad_frame qns:%s mc:%d md:%v\n",
				exampid, ltag, conn.Session(),
				qns, mc, md)
		}
		if !md.Message.Headers.ContainsKV("qnum", qns) || !md.Message.Headers.ContainsKV("msgnum", mns) {
			ll.Fatalf("%stag:%s connsess:%s dirty_message qns:%v msgnum:%v md:%v",
				exampid, tag, conn.Session(),
				qns, mns, md) // Handle this ......
		}

		sl := len(md.Message.Body)
		if pbc > 0 {
			sl = pbc
			if len(md.Message.Body) < sl {
				sl = len(md.Message.Body)
			}
		}

		ll.Printf("%stag:%s connsess:%s runReceive_recv_message id:%s body:%s qns:%s msgnum:%s\n",
			exampid, ltag, conn.Session(),
			id, string(md.Message.Body[0:sl]), qns,
			md.Message.Headers.Value("msgnum"))

		// Handle ACKs if needed
		if sngecomm.AckMode() != "auto" {
			ah := stompngo.Headers{}
			sngecomm.HandleAck(conn, ah, id)
		}
		if mc == nmsgs {
			break
		}
		if rw {
			dt := time.Duration(sngecomm.ValueBetween(min, max, rf))
			ll.Printf("%stag:%s connsess:%s recv_stagger dt:%v qns:%s mc:%d\n",
				exampid, ltag, conn.Session(),
				dt, qns, mc)
			tmr.Reset(dt)
			_ = <-tmr.C
			runtime.Gosched()
		}
	}
	// Unsubscribe
	sngecomm.HandleUnsubscribe(conn, d, id)

	ll.Printf("%stag:%s connsess:%s runRecieve_ends id:%s qns:%s\n",
		exampid, ltag, conn.Session(),
		id, qns)
	w.Done()
}
Beispiel #7
0
// Connect to a STOMP broker, receive some messages, ACK them, and disconnect.
func main() {

	st := time.Now()

	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	pbc := sngecomm.Pbc() // Print byte count

	// *NOTE* your application functionaltiy goes here!
	// With Stomp, you must SUBSCRIBE to a destination in order to receive.
	// Subscribe returns a channel of MessageData struct.
	// Here we use a common utility routine to handle the differing subscribe
	// requirements of each protocol level.
	d := senv.Dest()
	id := stompngo.Uuid()
	sc := sngecomm.HandleSubscribe(conn, d, id, "client")
	ll.Printf("%stag:%s connsess:%s main_subscribe_complete\n",
		exampid, tag, conn.Session())
	// Read data from the returned channel
	var md stompngo.MessageData
	for i := 1; i <= senv.Nmsgs(); i++ {

		select {
		case md = <-sc:
		case md = <-conn.MessageData:
			// Frames RECEIPT or ERROR not expected here
			ll.Fatalf("%stag:%s connsess:%s main_channel_frame error:%v",
				exampid, tag, conn.Session(),
				e.Error()) // Handle this ......
		}

		ll.Printf("%stag:%s connsess:%s main_channel_read_complete\n",
			exampid, tag, conn.Session())
		// MessageData has two components:
		// a) a Message struct
		// b) an Error value.  Check the error value as usual
		if md.Error != nil {
			ll.Fatalf("%stag:%s connsess:%s main_channel_read error:%v",
				exampid, tag, conn.Session(),
				e.Error()) // Handle this ......
		}
		//
		ll.Printf("%stag:%s connsess:%s frame_type:%v\n",
			exampid, tag, conn.Session(),
			md.Message.Command)
		if md.Message.Command != stompngo.MESSAGE {
			ll.Fatalf("%stag:%s connsess:%s bad_frame frame:%v",
				exampid, tag, conn.Session(),
				md.Message.Command) // Handle this ......
		}
		wh := md.Message.Headers
		for j := 0; j < len(wh)-1; j += 2 {
			ll.Printf("%stag:%s connsess:%s header:%s:%s\n",
				exampid, tag, conn.Session(),
				wh[j], wh[j+1])
		}
		if pbc > 0 {
			maxlen := pbc
			if len(md.Message.Body) < maxlen {
				maxlen = len(md.Message.Body)
			}
			ss := string(md.Message.Body[0:maxlen])
			ll.Printf("%stag:%s connsess:%s message_payload body:%s\n",
				exampid, tag, conn.Session(),
				ss)

		}
		// ACK the message just received.
		// Agiain we use a utility routine to handle the different requirements
		// of the protocol versions.
		sngecomm.HandleAck(conn, md.Message.Headers, id)
		ll.Printf("%stag:%s connsess:%s  ack_complete\n",
			exampid, tag, conn.Session())
	}
	// It is polite to unsubscribe, although unnecessary if a disconnect follows.
	// Again we use a utility routine to handle the different protocol level
	// requirements.
	sngecomm.HandleUnsubscribe(conn, d, id)
	ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n",
		exampid, tag, conn.Session())

	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s disconnect error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))

}
// Connect to a STOMP broker, subscribe and receive some messages and disconnect.
func main() {

	st := time.Now()

	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}
	session = conn.Session()
	conn.SetLogger(ll)              // stompngo logging
	pbc := sngecomm.Pbc()           // Print byte count
	d := senv.Dest()                // Destination
	id := stompngo.Uuid()           // A unique name/id
	nmsgs := senv.Nmsgs()           // int number of messages to get
	mns := fmt.Sprintf("%d", nmsgs) // string number of messages to get
	am := sngecomm.AckMode()        // ACK mode to use on SUBSCRIBE
	nfa := true                     // Need "final" ACK (possiby reset below)
	wh := stompngo.Headers{         // Starting SUBSCRIBE headers
		stompngo.StompPlusDrainAfter,
		mns} // Need a string here

	// Sanity check ACK mode
	if conn.Protocol() == stompngo.SPL_10 &&
		am == stompngo.AckModeClientIndividual {
		ll.Fatalf("%stag:%s connsess:%s invalid_ack_mode am:%v proto:%v\n",
			exampid, tag, session,
			am, conn.Protocol()) //
	}
	// Do not do final ACK if running ACKs are issued
	if am == stompngo.AckModeClientIndividual ||
		am == stompngo.AckModeAuto {
		nfa = false
	}

	// Show run parameters
	ll.Printf("%stag:%s connsess:%s run_parms\n\tpbc:%v\n\td:%v\n\tid:%v\n\tnmsgs:%v\n\tam:%v\n\tnfa:%v\n\twh:%v\n",
		exampid, tag, session,
		pbc, d, id, nmsgs, am, nfa, wh)

	// Run SUBSCRIBE
	sc := doSubscribe(conn, d, id, am, wh)
	ll.Printf("%stag:%s connsess:%s stomp_subscribe_complete\n",
		exampid, tag, session)

	var md stompngo.MessageData  // Message data from basic read
	var lmd stompngo.MessageData // Possible save (copy) of received data
	mc := 1                      // Initial message number

	// Loop for the requested number of messages
GetLoop:
	for {
		ll.Printf("%stag:%s connsess:%s start_of_read_loop mc:%v nmsgs:%v\n",
			exampid, tag, session, mc, nmsgs)

		mcs := fmt.Sprintf("%d", mc) // string number message count

		// Get something from the stompngo read routine
		select {
		case md = <-sc:
		case md = <-conn.MessageData:
			//
			if md.Message.Command == stompngo.RECEIPT {
				ll.Printf("%stag:%s connsess:%s have_receipt md:%v\n",
					exampid, tag, session,
					md)
				continue GetLoop
			}
			ll.Fatalf("%stag:%s connsess:%s ERROR_frame hdrs:%v body:%v\n",
				exampid, tag, session,
				md.Message.Headers, string(md.Message.Body)) // Handle this ......
		}

		// Save message data for possible use in the final ACK
		if mc == nmsgs && nfa {
			lmd = md // Save last message
		}

		// Basic loop logging
		ll.Printf("%stag:%s connsess:%s channel_read_complete mns:%s mc:%d\n",
			exampid, tag, session,
			mns, mc)
		ll.Printf("%stag:%s connsess:%s message_number:%v\n",
			exampid, tag, session,
			mc)

		// Check if reader returned any error
		if md.Error != nil {
			ll.Fatalf("%stag:%s connsess:%s error_read error:%v",
				exampid, tag, session,
				md.Error) // Handle this ......
		}

		// Show frame type
		ll.Printf("%stag:%s connsess:%s frame_type cmd:%s\n",
			exampid, tag, session,
			md.Message.Command)

		// Pure sanity check:  this should *never* happen based on logic
		// above.
		if md.Message.Command != stompngo.MESSAGE {
			ll.Fatalf("%stag:%s connsess:%s error_frame_type md:%v",
				exampid, tag, session,
				md) // Handle this ......
		}

		// Show Message Headers
		wh := md.Message.Headers
		for j := 0; j < len(wh)-1; j += 2 {
			ll.Printf("%stag:%s connsess:%s Header:%s:%s\n",
				exampid, tag, session,
				wh[j], wh[j+1])
		}
		// Show (part of) Message Body
		if pbc > 0 {
			maxlen := pbc
			if len(md.Message.Body) < maxlen {
				maxlen = len(md.Message.Body)
			}
			ss := string(md.Message.Body[0:maxlen])
			ll.Printf("%stag:%s connsess:%s payload body:%s\n",
				exampid, tag, session,
				ss)
		}

		// Sanity check this message payload
		wm := wlp + mcs // The left part plus the (string) meassage number]
		bm := string(md.Message.Body)
		if bm != wm {
			ll.Fatalf("%stag:%s connsess:%s error_message_payload\n\tGot %s\n\tWant%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......
		} else {
			ll.Printf("%stag:%s connsess:%s  matched_body_string\n%s\n%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......)
		}

		// Run individual ACK if required
		if am == stompngo.AckModeClientIndividual {
			wh := md.Message.Headers // Copy Headers
			if ar {                  // ACK receipt wanted
				wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-"+mcs)
			}
			sngecomm.HandleAck(conn, wh, id)
			ll.Printf("%stag:%s connsess:%s  individual_ack_complete mc:%v headers:%v\n",
				exampid, tag, session,
				mc, md.Message.Headers)
		}

		// Check for end of loop condition
		if mc == nmsgs {
			break
		}

		// Increment loop/message counter
		mc++
	}

	// Issue the final ACK if needed
	if nfa {
		wh := lmd.Message.Headers // Copy Headers
		if ar {                   // ACK receipt wanted
			wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-fin")
		}
		sngecomm.HandleAck(conn, wh, id)
		ll.Printf("%stag:%s connsess:%s  final_ack_complete\n",
			exampid, tag, session)
		if ar {
			getReceipt(conn)
		}
	}

	// Unsubscribe (may be skipped if requested)
	if unsub {
		sngecomm.HandleUnsubscribe(conn, d, id)
		ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n",
			exampid, tag, session)
	} else {
		ll.Printf("%stag:%s connsess:%s skipping_unsubscribe\n",
			exampid, tag, session)
	}

	// Standard example disconnect sequence (may be skipped if requested)
	// a) Closes the *stompngo.Connection
	// b) Closes the net.Conn
	if dodisc {
		e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s main_on_disconnect error:%v",
				exampid, tag, session,
				e.Error()) // Handle this ......
		}
		ll.Printf("%stag:%s connsess:%s disconnect_receipt:%v\n",
			exampid, tag, session,
			conn.DisconnectReceipt)
	} else {
		ll.Printf("%stag:%s connsess:%s skipping_disconnect\n",
			exampid, tag, session)
	}

	// End of work logging, show elapsed time
	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, session,
		time.Now().Sub(st))
}
func main() {

	st := time.Now()

	sngecomm.ShowRunParms(exampid)

	ll.Printf("%stag:%s connsess:%s main_starts\n",
		exampid, tag, sngecomm.Lcs)

	ll.Printf("%stag:%s connsess:%s main_profiling pprof:%v\n",
		exampid, tag, sngecomm.Lcs,
		sngecomm.Pprof())

	ll.Printf("%stag:%s connsess:%s main_current_GOMAXPROCS gmp:%v\n",
		exampid, tag, sngecomm.Lcs,
		runtime.GOMAXPROCS(-1))

	if sngecomm.SetMAXPROCS() {
		nc := runtime.NumCPU()
		ll.Printf("%stag:%s connsess:%s main_current_num_cpus cncpu:%v\n",
			exampid, tag, sngecomm.Lcs,
			nc)
		gmp := runtime.GOMAXPROCS(nc)
		ll.Printf("%stag:%s connsess:%s main_previous_num_cpus pncpu:%v\n",
			exampid, tag, sngecomm.Lcs,
			gmp)
		ll.Printf("%stag:%s connsess:%s main_current_GOMAXPROCS gmp:%v\n",
			exampid, tag, sngecomm.Lcs,
			runtime.GOMAXPROCS(-1))
	}
	//
	sw = sngecomm.SendWait()
	rw = sngecomm.RecvWait()
	sf = sngecomm.SendFactor()
	rf = sngecomm.RecvFactor()
	ll.Printf("%stag:%s connsess:%s main_wait_sleep_factors sw:%v rw:%v sf:%v rf:%v\n",
		exampid, tag, sngecomm.Lcs,
		sw, rw, sf, rf)
	//
	numq := sngecomm.Nqs()
	nmsgs = senv.Nmsgs() // message count
	//
	ll.Printf("%stag:%s connsess:%s main_starting_receivers\n",
		exampid, tag, sngecomm.Lcs)
	for q := 1; q <= numq; q++ {
		wgr.Add(1)
		go runReceiver(q)
	}
	ll.Printf("%stag:%s connsess:%s main_started_receivers\n",
		exampid, tag, sngecomm.Lcs)
	//
	ll.Printf("%stag:%s connsess:%s main_starting_senders\n",
		exampid, tag, sngecomm.Lcs)
	for q := 1; q <= numq; q++ {
		wgs.Add(1)
		go runSender(q)
	}
	ll.Printf("%stag:%s connsess:%s main_started_senders\n",
		exampid, tag, sngecomm.Lcs)
	//
	wgs.Wait()
	ll.Printf("%stag:%s connsess:%s main_senders_complete\n",
		exampid, tag, sngecomm.Lcs)
	wgr.Wait()
	ll.Printf("%stag:%s connsess:%s main_receivers_complete\n",
		exampid, tag, sngecomm.Lcs)
	//

	// The end
	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, sngecomm.Lcs,
		time.Now().Sub(st))

}
	// We 'stagger' between each message send and message receive for a random
	// amount of time.
	// Vary these for experimental purposes.  YMMV.
	max int64 = 1e9      // Max stagger time (nanoseconds)
	min int64 = max / 10 // Min stagger time (nanoseconds)

	// Wait flags
	sw = true
	rw = true

	// Sleep multipliers
	sf float64 = 1.0
	rf float64 = 1.0

	// Number of messages
	nmsgs = senv.Nmsgs()

	ll = log.New(os.Stdout, "EMSMR ", log.Ldate|log.Lmicroseconds|log.Lshortfile)

	tag = "manyconn"
)

func sendMessages(conn *stompngo.Connection, qnum int, nc net.Conn) {
	ltag := tag + "-sendmessages"

	qns := fmt.Sprintf("%d", qnum) // queue number
	d := sngecomm.Dest() + "." + qns
	ll.Printf("%stag:%s connsess:%s start d:%s qnum:%d\n",
		exampid, ltag, conn.Session(),
		d, qnum)
	wh := stompngo.Headers{"destination", d,