using stomp function in golang - go

I am trying to establish a stomp connection using stomp.dial() function at the client side, but unable to connect to the server.
I am using go-stomp library. I tried different methods like using net.connect and then stomp.connect, but its resulting in the same error. the error goes like
read tcp: wsarecv: An existing connection was forcibly closed by the remote host
What is exactly happening here and how to resolve it
My code looks something like
ticker := time.NewTicker(time.Second * 5)
defer ticker.Stop()
for ; ; <-ticker.C {
st, err := stomp.Dial("tcp", conn.ConfigStr)
if err != nil {
log.Println("Stomp connect error", err.Error())
continue
}
log.Println("CONNECTED TO ", conn.ProviderName)

I was able to accomplish your request in this way.
First I run a STOMP server locally on port 61613. To launch it, I used this command:
docker run -it --rm -p 61613:61613 efrecon/stomp -verbose 5
Then, I used the package go-stomp together with the function Dial to connect to it:
package main
import "github.com/go-stomp/stomp/v3"
func main() {
conn, err := stomp.Dial("tcp", "localhost:61613")
if err != nil {
panic(err)
}
defer func() {
if err = conn.Disconnect(); err != nil {
panic(err)
}
}()
}
Lastly, I used the Disconnect method to close the connection.
Let me know if this works also for you.

Related

Program fails with: write tcp broken pipe error

I've got a go app that downloads files using github.com/jlaffaye/ftp which is a library that implements File Transfer Protocol (FTP)
Defined a struct with an FTP connection
type Client struct {
conn *ftp.ServerConn
sync.Mutex
}
I have a global client
var cli *Client = nil
Which I then initialize and assign to the global variable to be used later
conn, err := ftp.Dial(cfg.Host+cfg.Port, ftp.DialWithContext(ctx))
if err != nil {
return fmt.Errorf("ftp dial error: %v", err)
}
err = conn.Login(cfg.Username, pwd)
if err != nil {
return fmt.Errorf("ftp login error: %v", err)
}
c := &Client{}
c.Lock()
c.conn = conn
cli = c
c.Unlock()
I've got a http handler that takes the conn field from the Client struct and calls
fileNames, err := conn.NameList(".")
if err != nil {
return err
}
Most of the time, the application fails on the call to conn.NameList(".") with error
write tcp xxx.xxx.xx.x:48572-\u003exx.xxx.xxx.xxx:21: write: broken pipe
And sometimes
write tcp xxx.xxx.xx.xx:63037-\u003exx.xxx.xxx.xxx:21: wsasend: An established connection was aborted by the software in your host machine
I don't close the connection prematurely.
Does anyone have an idea on why this is happening? Or maybe you could recommend a better library that uses FTP?
As per the question if multiple services are running at the same time, and if it's conccurently safe.
When a process is running, another can't run until setIsRunning(false) is called
func (s *Service) setIsRunning(b bool) error {
mu := &sync.Mutex{}
mu.Lock()
defer mu.Unlock()
if b && s.isRunning {
return errors.New("already running")
}
s.isRunning = b
return nil
}
An attempt to call that handler while its running will yield
"error":"already running"
Also I use mutex locks while reading from the global Client like such
cli.Lock()
conn = cli.conn
cli.Unlock()
switching to a non-global client resolves the issue

Testing NATS-streaming in Kubernetes with minimal effort

I wanted to test a very basic application for NATS-streaming on Kubernetes. To do so, I followed the commands from the official NATS-docs.
It basically comes down to running
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-server/single-server-nats.yml
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-streaming-server/single-server-stan.yml
in a terminal with access to the cluster (it's a kind-cluster in my case).
I used stan.go as the NATS-streaming-client. Here is the code I tried to connect to the NATS-streaming-server:
package main
import stan "github.com/nats-io/stan.go"
func main() {
sc, err := stan.Connect("stan", "test-client")
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}
and this is the error I'm getting:
panic: nats: no servers available for connection
goroutine 1 [running]:
main.main()
/Users/thilt/tmp/main.go:9 +0x15d
exit status 2
so I think another name was used for the cluster or something. If I use the provided example with nats-box from the docs.nats-link above, it also doesn't work! Where did I go wrong here?
I will happily provide more information, if needed.
There is a great example in stan.go docs:
// Connect to NATS
nc, err := nats.Connect(URL, opts...)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
sc, err := stan.Connect(clusterID, clientID, stan.NatsConn(nc))
if err != nil {
log.Fatalf("Can't connect: %v.\nMake sure a NATS Streaming Server is running at: %s", err, URL)
}
defer sc.Close()
Your error happens because by default stan connects to localhost address (source code):
// DefaultNatsURL is the default URL the client connects to
DefaultNatsURL = "nats://127.0.0.1:4222"
Notice that povided above example overwrite this default connection.
Stan source code is short and easy to analyze. I really recommend you to try to analyze it and figure out what it does.
Now let's put it all together; here is a working example:
package main
import (
nats "github.com/nats-io/nats.go"
stan "github.com/nats-io/stan.go"
)
func main() {
// Create a NATS connection
nc, err := nats.Connect("nats://nats:4222")
if err != nil {
panic(err)
}
// Then pass it to the stan.Connect() call.
sc, err := stan.Connect("stan", "me", stan.NatsConn(nc))
if err != nil {
panic(err)
}
if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
panic(err)
}
}

TCP connection between different hosts on different connections

I am trying to make a TCP connection where 2 hosts are on different networks. I have made a client and server in go lang
Server.go
func main() {
l, err := net.Listen("tcp",":8000")
if err != nil{
log.Fatal(err)
}
for{
conn,err := l.Accept()
if err != nil{
log.Println(err)
return
}
go serve(conn)
}
}
func serve(connection net.Conn){
defer connection.Close()
for{
buffer := make([]byte,1024)
_,err := connection.Read(buffer[:])
if err != nil{
log.Println(err)
return
}
fmt.Println(string(buffer))
}
}
client.go
func main() {
c, err := net.Dial("tcp",":8000")
if err != nil{
log.Fatal(err)
}
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan(){
_,err := c.Write([]byte(scanner.Text()))
if err != nil{
log.Fatal(err)
}
}
}
when I run my server.go and use telnet on a device that is on the same network to send messages to the server, it works without any problem. I can send messages and it will show up in the console.
But when I try to run telnet on a device with a different network, it does not work. I try to send a message and nothing appears in the console. I then get a message something along the lines of connection closed by the foreign host.
I am a bit of a newbie in networking, I don't understand why is it not able to show any messages from another device on another network.
How do I achieve a TCP connection between 2 different hosts on different connections in go lang?
thanks.
You should call through an external address, not a local address:
Find the external address of your server application host. Put it in client code:
For example:
c, err := net.Dial("tcp","45.44.230.205:8000")
That's it

"connect: connection refused" while attempting to connect to localhost

I'm currently attempting to create a TCP service that will just log/store whatever is sent to it. I can't seem to understand why I cannot connect to my localhost using DialTCP. I keep getting
dial tcp 127.0.0.1:8080: connect: connection refused
func main() {
errCh := make(chan error)
tcpAddr, _ := net.ResolveTCPAddr("tcp", "localhost:8080")
for {
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
log.Println("Could not connect -> ", err.Error())
} else {
recordMessage(conn, errCh)
err = <-errCh
log.Println("Error", err)
conn.Close()
}
log.Println("trying again in 10 seconds..")
time.Sleep(30 * time.Second)
}
}
I looked over my Firewall settings and noting seems to be blocking it. I'm still not sure if its due to something related to my Firewall or if I'm just missing something super obvious.
Start by running this Go program in a terminal -- it listens to port 2000 but you could change it to 8080 or whatever you wish:
func main() {
// Listen on TCP port 2000 on all interfaces.
l, err := net.Listen("tcp", ":2000")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// Handle the connection in a new goroutine.
// The loop then returns to accepting, so that
// multiple connections may be served concurrently.
go func(c net.Conn) {
log.Println(c)
// Echo all incoming data.
io.Copy(c, c)
// Shut down the connection.
c.Close()
}(conn)
}
}
Then in a separate terminal run this simple client:
func main() {
var addr string
if len(os.Args) > 1 {
addr = os.Args[1]
} else {
addr = "localhost:2000"
}
conn, err := net.Dial("tcp", addr)
if err != nil {
log.Fatal(err)
// handle error
}
fmt.Fprintf(conn, "foobar")
conn.Close()
}
Asking it to connect to the same port. The connection should succeed and you should see the server logging something.
Now try to connect with your client.
Without writing Go, you could to these things with the nc command-line tool (netcat). nc -lv PORT creates a simple listening server on PORT, for example.

Go net.dial issue

I'm having some issues connecting to a local golang TLS server via tls.dial or net.dial. The server ist started with the address localhost:10001 and I am able to connect to it with netcat (simply netcat localhost 10001 ) but trying it with golangs's dial method doesn't work (connection refused). What could be the reason for this? One important thing to point out is that I'm testing it on a Debian VM where I deinstalled the network manager so I could configure the network interfaces myself (static ip). My guess is that net.dial has some issues finding the right interface but what does netcat do that golang's methods don't? I tried all different kinds of addresses on both sides (server on localhost, ::1, 127.0.0.1; client same). On my windows host system it works (so the issue is probably not with the server).
Thanks in advance.
conn, err := tls.Dial("tcp", h.IP+":"+h.Port, conf)
if err != nil {
log.Println(err)
return empty
}
// do cleanup
defer conn.Close()
d := Craft_PKG( data )
//write package
WriteChunks( conn, d )
this is the client code and this
ln, err := tls.Listen("tcp", "localhost:"+(*port), config)
if err != nil {
log.Println(err)
return err
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
// start the handler for every incoming connection
go h(conn)
}
the server code. It is all very straightforward and works with netcat and in my Host system as I mentioned.

Resources