I am using Redigo to connect to redis server through golang.
redisConnection, err = redis.Dial("tcp", "...")
redisConnection.Do(..., ...)
If I restart my server, I am unable to execute any command using the same redisConnection. Shouldn't it reconnect when I execute Do again?
No, your assumption is not correct. Using the Dial function it returns a single connection when the server terminates the connection, the client is not able to reconnect.
You should use redis.Pool and it should be able to auto-reconnect when you ask for a new connection, the function is: pool.Get()
redisConnection.Err() returns a non nil value if the connection is not usable. We can Dial again in that case.
Related
I am trying to build a bittorrent client. I wrote this function to verify that I can establish connection to send messages to other peers but its not working.
func handShake(torrent *gotorrentparser.Torrent, peer Peer, peedId []byte) {
conn,err := net.Dial("tcp", peer.ip + ":" + strconv.Itoa(int(peer.port)))
if err != nil {
panic(err)
}
defer conn.Close()
}
Here peer is a struct of string ip and uint16 port.
Getting the following error:
panic: dial tcp 152.57.73.47:27569: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
Couldn't find any similar issues. I tried to fix my local port address to be same as what I used to send the announce request but that didn't work either.
Edit: I tried with a different torrent, it is failing for some peers, but now it is working for some other peers. Is the issue only when the peer is using utorrent as bittorrent clients?
If you're developing a bittorrent client you should start with a more reproducable setup such as running an existing client with a known infohash on your local machine and then connecting to that (without using a tracker). Once you got that to work you can work on a tracker client implementation and then put those pieces together.
The internet is unreliable and bittorrent consists of many moving parts, so a single connection failure won't tell you much, you'll have to ensure that each part works properly and try with torrents that you have tested in an existing client to narrow down the cause of problems.
After few days here is the problem that I found.
Not all peers are able to accept an inbound request as they are behind a NAT.
Even when I hosted a torrent from one of my computer and tried to download through another system, I couldn't download as there was no reply from the peer for the SYN message being sent.
I was only able to download, when both the clients were on the same network and local peer discovery was enabled, and the TCP connection was also build with the local IP address.
I am working on an application that tries to send some data to a remote server. Once I get the hostname, I get a connection by resolving the hostname using net.Dialer.DialContext. Once, I resolve the hostname, I keep on using conn.Write method to write data to the connection.
conn, err := d.DialContext(ctx, string(transport), addr)
_, err := client.conn.Write([]byte(msg))
Error faced: I observed that due to some issues, I was not able to ping my server. Surprisingly, conn obtained from DialContext did not complain while doing conn.Write and it kept writing to the same connection.
Can someone help me in how to modify my writing methods in order to get an error in case the destination server is not reachable?
From this UDP connection example
the best a "connected" UDP socket can do to simulate a send failure is to save the ICMP response, and return it as an error on the next write.
So try and (for testing) make a second conn.Write, to confirm that you would indeed get an error this time.
I work on agent demon which runs on a node. When we start the agent, all the ssh connections to the other nodes are built and later on at particular time intervals(weekly once) we create new sessions on these ssh connections to communicate with the other nodes. but it has been observed that after 1 month around the time frame, the session creation would give EOF error.
User: config.Username,
Auth: []ssh.AuthMethod{
ssh.Password(config.Password),
},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
}
client, err := ssh.Dial("tcp", config.Host+":22", sshConfig)
session, err := client.NewSession()
defer session.Close()
b, err := session.CombinedOutput(command)
When this session creation gives EOF error, is there any way to get back the ssh connection in working state?
If I consider redialing or reconnect when only if I get error on read/write then which design pattren will be useful here.
Thanks
I think the problem is connection getting broken after sometime, a few things you can try is
Create a mechanism to keep the connection alive if the server provides with an api or ping to increase connection expire time. like github.com/felixge/tcpkeepalive
Or Try re dialing the connection at a fixed time interval.
In Go/Golang, once a connection object (Conn) is created with the following code:
conn, err := net.Dial("tcp","33.33.33.33:444")
if err != nil {
// good connection
}
I would like to preserve the conn value for later on verifying if the connection is active. I dont want to re-connect from time to time to check the connection as it causes various TIME_WAITs on the OS, so overall my requirements are:
create a connection
preserve the connection object
capture if the connection drops for any reason
do not send or receive any data
Any thoughts on how to achieve this ? Is there a way to capture that the connection is discontinued without sending or receiving data or reconnecting ?
I don't think it is possible to do without performing an operation. If it is infrequently used, when you try to read you may get an error if the client (or some proxy) closed the connection. If that happens then reconnect and retry.
Many protocols will bake in a heartbeat mechanism to facilitate this kind of thing. Then you can read constantly (with SetDeadline if you want) and know within a heartbeat frame that something went wrong.
For example, I use a redis client that supports connection pooling. When I retrieve an idele connection from the pool, I immediately perform a PING operation. If that succeeds, I know the connection is ready to use. If not, I get another idle one, or connect anew.
I'm studying Go for network programming. The problem is Go documentation is too simple. For example, I don't know when to use net.DialTCP, and when to use TCPListener object to AcceptTCP, what's the difference? How about client communicate with another client? Not client to server.
Connecting
In Go, you use the Dial function from net to connect to a remote machine.
net.Dial("tcp","google.com:80")
net.Dial("udp","tracker.thepiratebay.org:6969")
net.Dial("ip","kremvax.su")
net.Dial("unix","/dev/log")
This gives you an abstract Conn object that represents the connection you just established. Conn implements the ReadWriteCloser interface from io and a couple of other functions. You can use this object to send and receive data.
Listening
To listen, i.e. open a port, you use the Listen function from net. Calling Listen gives you a Listener object. Use Accept to accept incoming connections. Accept returns another Conn object that can be used as above.
ls, err := net.Listen("tcp",":1337")
if err != nil {
// port probably blocked, insert error handling here
}
conn, err := ls.Accept()
if err != nil {
// error handling
}
conn.Write("Hello, world!")
DialTCP and ListenTCP
These functions give you more control over TCP connections. I suggest you to only use them if they are definitly needed for your program as Dial and Listen are simpler, more generic and easily allow you to adapt your program to other types of network connections.
net.DialTCP is used on the client side to create a connection to remote server.
net.TCPListener.AcceptTCP is used on the server side to accept new connection (possibly initiated by net.DialTCP if client is written in Go). Note that listener may accept multiple connections, one by one, thus serving multiple clients at once (e.g. each in different goroutine).
Depending on whether you are writing client or server, you use net.DialTCP or net.TCPListener
Maybe you should learn about network programming in general first? Then these would make more sense I think.