forked from zheng-ji/goTcpProxy
/
server.go
134 lines (113 loc) · 2.75 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// zheng-ji.info
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"time"
)
var (
src = flag.String("src", "127.0.0.1:8999", "proxy server's host.")
dest = flag.String("dest", "172.16.1.250:3306", "where proxy server forward requests to.")
maxConn = flag.Int("n", 25, "max active connection.")
maxWaitQueue = flag.Int("c", 10000, "max connections in the queue wait for servers.")
expire = flag.Int("ttl", 20, "timeout of read and write")
)
func main() {
flag.Parse()
fmt.Printf("Proxying %s->%s.\n", *src, *dest)
server, err := net.Listen("tcp", *src)
if err != nil {
log.Fatal(err)
}
waitQueue := make(chan net.Conn, *maxWaitQueue)
availPools := make(chan bool, *maxConn)
for i := 0; i < *maxConn; i++ {
availPools <- true
}
go loop(waitQueue, availPools)
go onExitSignal()
for {
connection, err := server.Accept()
if err != nil {
log.Print(err)
} else {
log.Printf("Received connection from %s.\n", connection.RemoteAddr())
waitQueue <- connection
}
}
}
func onExitSignal() {
sigChan := make(chan os.Signal)
signal.Notify(sigChan, syscall.SIGUSR1, syscall.SIGTERM, syscall.SIGINT)
L:
for {
sig := <-sigChan
switch sig {
case syscall.SIGUSR1:
log.Fatal("Reopen log file")
case syscall.SIGTERM, syscall.SIGINT:
log.Fatal("Catch SIGTERM singal, exit.")
break L
}
}
}
func loop(waitQueue chan net.Conn, availPools chan bool) {
for connection := range waitQueue {
<-availPools
go func(connection net.Conn) {
handleConnection(connection)
availPools <- true
log.Printf("Closed connection from %s.\n", connection.RemoteAddr())
}(connection)
}
}
func handleConnection(connection net.Conn) {
defer connection.Close()
remote, err := net.Dial("tcp", *dest)
defer remote.Close()
if err != nil {
log.Print(err)
return
}
//等待双向连接完成
complete := make(chan bool, 2)
one_side := make(chan bool, 1)
other_side := make(chan bool, 1)
go pass(connection, remote, complete, one_side, other_side)
go pass(remote, connection, complete, other_side, one_side)
<-complete
<-complete
}
// copy Content two-way
func pass(from net.Conn, to net.Conn, complete chan bool, one_side chan bool, other_side chan bool) {
var err error = nil
var bytes []byte = make([]byte, 256)
var read int = 0
for {
select {
case <-other_side:
complete <- true
return
default:
from.SetReadDeadline(time.Now().Add(time.Duration(*expire) * time.Second))
read, err = from.Read(bytes)
if err != nil {
complete <- true
one_side <- true
return
}
to.SetWriteDeadline(time.Now().Add(time.Duration(*expire) * time.Second))
_, err = to.Write(bytes[:read])
if err != nil {
complete <- true
one_side <- true
return
}
}
}
}