2016-07-26 11:25:46 +00:00
# TCP Checker :heartbeat:
2019-01-31 07:27:44 +00:00
2016-06-28 10:10:56 +00:00
[![Go Report Card ](https://goreportcard.com/badge/github.com/tevino/tcp-shaker )](https://goreportcard.com/report/github.com/tevino/tcp-shaker)
2016-06-01 04:07:09 +00:00
[![GoDoc ](https://godoc.org/github.com/tevino/tcp-shaker?status.svg )](https://godoc.org/github.com/tevino/tcp-shaker)
2019-02-13 02:40:18 +00:00
[![Build Status ](https://travis-ci.org/tevino/tcp-shaker.svg?branch=master )](https://travis-ci.org/tevino/tcp-shaker)
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
This package is used to perform TCP handshake without ACK, which useful for TCP health checking.
2016-06-01 04:07:09 +00:00
2016-06-01 11:02:11 +00:00
HAProxy does this exactly the same, which is:
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
1. SYN
2. SYN-ACK
3. RST
2016-06-01 04:07:09 +00:00
2019-11-12 10:45:05 +00:00
This implementation has been running on tens of thousands of production servers for years.
2019-02-11 10:42:37 +00:00
## Why do I have to do this
2019-01-31 07:27:44 +00:00
2019-02-11 10:42:37 +00:00
In most cases when you establish a TCP connection(e.g. via `net.Dial` ), these are the first three packets between the client and server([TCP three-way handshake][tcp-handshake]):
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
1. Client -> Server: SYN
2. Server -> Client: SYN-ACK
3. Client -> Server: ACK
2016-06-01 04:07:09 +00:00
**This package tries to avoid the last ACK when doing handshakes.**
By sending the last ACK, the connection is considered established.
2019-02-11 10:42:37 +00:00
However, as for TCP health checking the server could be considered alive right after it sends back SYN-ACK,
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
that renders the last ACK unnecessary or even harmful in some cases.
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
### Benefits
By avoiding the last ACK
2019-01-31 07:27:44 +00:00
2016-06-01 04:07:09 +00:00
1. Less packets better efficiency
2. The health checking is less obvious
2019-02-11 10:42:37 +00:00
The second one is essential because it bothers the server less.
2016-06-01 04:07:09 +00:00
2019-02-11 10:42:37 +00:00
This means the application level server will not notice the health checking traffic at all, **thus the act of health checking will not be
considered as some misbehavior of client.**
2016-06-01 04:07:09 +00:00
2019-01-31 07:27:44 +00:00
## Requirements
2016-06-01 04:07:09 +00:00
- Linux 2.4 or newer
2016-12-06 09:20:41 +00:00
There is a **fake implementation** for **non-Linux** platform which is equivalent to:
2019-11-12 10:45:05 +00:00
2016-12-06 09:20:41 +00:00
```go
conn, err := net.DialTimeout("tcp", addr, timeout)
conn.Close()
```
2016-06-01 10:23:31 +00:00
## Usage
2019-01-31 07:27:44 +00:00
2016-06-01 10:23:31 +00:00
```go
2019-11-12 10:22:14 +00:00
import "github.com/tevino/tcp-shaker"
c := NewChecker()
ctx, stopChecker := context.WithCancel(context.Background())
defer stopChecker()
go func() {
if err := c.CheckingLoop(ctx); err != nil {
fmt.Println("checking loop stopped due to fatal error: ", err)
2016-06-01 10:23:31 +00:00
}
2019-11-12 10:22:14 +00:00
}()
< -c.WaitReady ( )
timeout := time.Second * 1
err := c.CheckAddr("google.com:80", timeout)
switch err {
case ErrTimeout:
fmt.Println("Connect to Google timed out")
case nil:
fmt.Println("Connect to Google succeeded")
default:
fmt.Println("Error occurred while connecting: ", err)
}
2016-06-01 10:23:31 +00:00
```
2019-01-31 07:27:44 +00:00
## TODO
2016-06-01 04:07:09 +00:00
2016-07-22 11:31:45 +00:00
- [ ] IPv6 support (Test environment needed, PRs are welcome)
2019-02-11 10:42:37 +00:00
2019-02-12 07:08:48 +00:00
## Special thanks to contributors
2019-11-12 08:06:07 +00:00
- @lujjjh Added zero linger support for non-Linux platform
2019-11-12 07:57:04 +00:00
- @jakubgs Fixed compatibility on Android
2019-02-12 07:08:48 +00:00
[tcp-handshake]: https://en.wikipedia.org/wiki/Handshaking#TCP_three-way_handshake