forked from hyper0x/Golang_Puzzlers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
794 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"syscall" | ||
) | ||
|
||
func main() { | ||
fd1, err := syscall.Socket( | ||
syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) | ||
if err != nil { | ||
fmt.Printf("socket error: %v\n", err) | ||
return | ||
} | ||
defer syscall.Close(fd1) | ||
fmt.Printf("The file descriptor of socket:%d\n", fd1) | ||
|
||
// 省略若干代码。 | ||
// 如果真要完全使用syscall包中的程序实体建立网络连接的话, | ||
// 过程太过繁琐而且完全没有必要。 | ||
// 所以,我在这里就不做展示了。 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"crypto/tls" | ||
"fmt" | ||
"io" | ||
"net" | ||
"runtime" | ||
) | ||
|
||
func main() { | ||
network := "tcp" | ||
host := "google.cn" | ||
reqStrTpl := `HEAD / HTTP/1.1 | ||
Accept: */* | ||
Accept-Encoding: gzip, deflate | ||
Connection: keep-alive | ||
Host: %s | ||
User-Agent: Dialer/%s | ||
` | ||
|
||
// 示例1。 | ||
network1 := network + "4" | ||
address1 := host + ":80" | ||
fmt.Printf("Dial %q with network %q ...\n", address1, network1) | ||
conn1, err := net.Dial(network1, address1) | ||
if err != nil { | ||
fmt.Printf("dial error: %v\n", err) | ||
return | ||
} | ||
defer conn1.Close() | ||
|
||
reqStr1 := fmt.Sprintf(reqStrTpl, host, runtime.Version()) | ||
fmt.Printf("The request:\n%s\n", reqStr1) | ||
_, err = io.WriteString(conn1, reqStr1) | ||
if err != nil { | ||
fmt.Printf("write error: %v\n", err) | ||
return | ||
} | ||
fmt.Println() | ||
|
||
reader1 := bufio.NewReader(conn1) | ||
line1, err := reader1.ReadString('\n') | ||
if err != nil { | ||
fmt.Printf("read error: %v\n", err) | ||
return | ||
} | ||
fmt.Printf("The first line of response:\n%s\n", line1) | ||
fmt.Println() | ||
|
||
// 示例2。 | ||
tlsConf := &tls.Config{ | ||
InsecureSkipVerify: true, | ||
MinVersion: tls.VersionTLS10, | ||
} | ||
network2 := network | ||
address2 := host + ":443" | ||
fmt.Printf("Dial %q with network %q ...\n", address2, network2) | ||
conn2, err := tls.Dial(network2, address2, tlsConf) | ||
if err != nil { | ||
fmt.Printf("dial error: %v\n", err) | ||
return | ||
} | ||
defer conn2.Close() | ||
|
||
reqStr2 := fmt.Sprintf(reqStrTpl, host, runtime.Version()) | ||
fmt.Printf("The request:\n%s\n", reqStr2) | ||
_, err = io.WriteString(conn2, reqStr2) | ||
if err != nil { | ||
fmt.Printf("write error: %v\n", err) | ||
return | ||
} | ||
|
||
reader2 := bufio.NewReader(conn2) | ||
line2, err := reader2.ReadString('\n') | ||
if err != nil { | ||
fmt.Printf("read error: %v\n", err) | ||
return | ||
} | ||
fmt.Printf("The first line of response:\n%s\n", line2) | ||
fmt.Println() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"time" | ||
) | ||
|
||
type dailArgs struct { | ||
network string | ||
address string | ||
timeout time.Duration | ||
} | ||
|
||
func main() { | ||
dialArgsList := []dailArgs{ | ||
{ | ||
"tcp", | ||
"google.cn:80", | ||
time.Millisecond * 500, | ||
}, | ||
{ | ||
"tcp", | ||
"google.com:80", | ||
time.Second * 2, | ||
}, | ||
{ | ||
// 如果在这种情况下发生的错误是: | ||
// "connect: operation timed out", | ||
// 那么代表着什么呢? | ||
// | ||
// 简单来说,此错误表示底层的socket在连接网络服务的时候先超时了。 | ||
// 这时抛出的其实是'syscall.ETIMEDOUT'常量代表的错误值。 | ||
"tcp", | ||
"google.com:80", | ||
time.Minute * 4, | ||
}, | ||
} | ||
for _, args := range dialArgsList { | ||
fmt.Printf("Dial %q with network %q and timeout %s ...\n", | ||
args.address, args.network, args.timeout) | ||
ts1 := time.Now() | ||
conn, err := net.DialTimeout(args.network, args.address, args.timeout) | ||
ts2 := time.Now() | ||
fmt.Printf("Elapsed time: %s\n", time.Duration(ts2.Sub(ts1))) | ||
if err != nil { | ||
fmt.Printf("dial error: %v\n", err) | ||
fmt.Println() | ||
continue | ||
} | ||
defer conn.Close() | ||
fmt.Printf("The local address: %s\n", conn.LocalAddr()) | ||
fmt.Printf("The remote address: %s\n", conn.RemoteAddr()) | ||
fmt.Println() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
func main() { | ||
host := "google.cn" | ||
|
||
// 示例1。 | ||
url1 := "http://" + host | ||
fmt.Printf("Send request to %q with method GET ...\n", url1) | ||
resp1, err := http.Get(url1) | ||
if err != nil { | ||
fmt.Printf("request sending error: %v\n", err) | ||
return | ||
} | ||
defer resp1.Body.Close() | ||
line1 := resp1.Proto + " " + resp1.Status | ||
fmt.Printf("The first line of response:\n%s\n", line1) | ||
fmt.Println() | ||
|
||
// 示例2。 | ||
url2 := "https://golang." + host | ||
fmt.Printf("Send request to %q with method GET ...\n", url2) | ||
var httpClient1 http.Client | ||
resp2, err := httpClient1.Get(url2) | ||
if err != nil { | ||
fmt.Printf("request sending error: %v\n", err) | ||
return | ||
} | ||
defer resp2.Body.Close() | ||
line2 := resp2.Proto + " " + resp2.Status | ||
fmt.Printf("The first line of response:\n%s\n", line2) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"net/http" | ||
"strings" | ||
"sync" | ||
"time" | ||
) | ||
|
||
// domains 包含了我们将要访问的一些网络域名。 | ||
// 你可以随意地对它们进行增、删、改, | ||
// 不过这会影响到后面的输出内容。 | ||
var domains = []string{ | ||
"google.com", | ||
"google.com.hk", | ||
"google.cn", | ||
"golang.org", | ||
"golang.google.cn", | ||
} | ||
|
||
func main() { | ||
// 你可以改变myTransport中的各个字段的值, | ||
// 并观察后面的输出会有什么不同。 | ||
myTransport := &http.Transport{ | ||
Proxy: http.ProxyFromEnvironment, | ||
DialContext: (&net.Dialer{ | ||
Timeout: 15 * time.Second, | ||
KeepAlive: 15 * time.Second, | ||
DualStack: true, | ||
}).DialContext, | ||
MaxConnsPerHost: 2, | ||
MaxIdleConns: 10, | ||
MaxIdleConnsPerHost: 2, | ||
IdleConnTimeout: 30 * time.Second, | ||
ResponseHeaderTimeout: 0, | ||
ExpectContinueTimeout: 1 * time.Second, | ||
TLSHandshakeTimeout: 10 * time.Second, | ||
} | ||
// 你可以改变myClient中的各个字段的值, | ||
// 并观察后面的输出会有什么不同。 | ||
myClient := http.Client{ | ||
Transport: myTransport, | ||
Timeout: 20 * time.Second, | ||
} | ||
|
||
var wg sync.WaitGroup | ||
wg.Add(len(domains)) | ||
for _, domain := range domains { | ||
go func(domain string) { | ||
var logBuf strings.Builder | ||
var diff time.Duration | ||
defer func() { | ||
logBuf.WriteString( | ||
fmt.Sprintf("(elapsed time: %s)\n", diff)) | ||
fmt.Println(logBuf.String()) | ||
wg.Done() | ||
}() | ||
url := "https://" + domain | ||
logBuf.WriteString( | ||
fmt.Sprintf("Send request to %q with method GET ...\n", url)) | ||
t1 := time.Now() | ||
resp, err := myClient.Get(url) | ||
diff = time.Now().Sub(t1) | ||
if err != nil { | ||
logBuf.WriteString( | ||
fmt.Sprintf("request sending error: %v\n", err)) | ||
return | ||
} | ||
defer resp.Body.Close() | ||
line2 := resp.Proto + " " + resp.Status | ||
logBuf.WriteString( | ||
fmt.Sprintf("The first line of response:\n%s\n", line2)) | ||
}(domain) | ||
} | ||
wg.Wait() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"sync" | ||
) | ||
|
||
func main() { | ||
var wg sync.WaitGroup | ||
wg.Add(2) | ||
|
||
// 示例1。 | ||
go startServer1(&wg) | ||
|
||
// 示例2。 | ||
go startServer2(&wg) | ||
|
||
wg.Wait() | ||
} | ||
|
||
func startServer1(wg *sync.WaitGroup) { | ||
defer wg.Done() | ||
var httpServer1 http.Server | ||
httpServer1.Addr = "127.0.0.1:8080" | ||
// 由于我们没有定制handler,所以这个网络服务对任何请求都只会响应404。 | ||
if err := httpServer1.ListenAndServe(); err != nil { | ||
if err == http.ErrServerClosed { | ||
log.Println("HTTP server 1 closed.") | ||
} else { | ||
log.Printf("HTTP server 1 error: %v\n", err) | ||
} | ||
} | ||
} | ||
|
||
func startServer2(wg *sync.WaitGroup) { | ||
defer wg.Done() | ||
mux1 := http.NewServeMux() | ||
mux1.HandleFunc("/hi", func(w http.ResponseWriter, req *http.Request) { | ||
if req.URL.Path != "/hi" { | ||
http.NotFound(w, req) | ||
return | ||
} | ||
name := req.FormValue("name") | ||
if name == "" { | ||
fmt.Fprint(w, "Welcome!") | ||
} else { | ||
fmt.Fprintf(w, "Welcome, %s!", name) | ||
} | ||
}) | ||
httpServer2 := http.Server{ | ||
Addr: "127.0.0.1:8081", | ||
Handler: mux1, | ||
} | ||
if err := httpServer2.ListenAndServe(); err != nil { | ||
if err == http.ErrServerClosed { | ||
log.Println("HTTP server 2 closed.") | ||
} else { | ||
log.Printf("HTTP server 2 error: %v\n", err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package common | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"time" | ||
) | ||
|
||
// OpFunc 代表包含高负载操作的函数。 | ||
type OpFunc func() error | ||
|
||
// Execute 用于执行可以产生高负载的操作。 | ||
func Execute(op OpFunc, times int) (err error) { | ||
if op == nil { | ||
return errors.New("nil operation function") | ||
} | ||
if times <= 0 { | ||
return fmt.Errorf("invalid times: %d", times) | ||
} | ||
var t1 time.Time | ||
defer func() { | ||
diff := time.Now().Sub(t1) | ||
fmt.Printf("(elapsed time: %s)\n", diff) | ||
if p := recover(); p != nil { | ||
err = fmt.Errorf("fatal error: %v", p) | ||
} | ||
}() | ||
t1 = time.Now() | ||
for i := 0; i < times; i++ { | ||
if err = op(); err != nil { | ||
return | ||
} | ||
time.Sleep(time.Microsecond) | ||
} | ||
return | ||
} | ||
|
||
// CreateFile 用于在当前目录下创建一个指定名称的文件。 | ||
// 若同名文件已存在,则清空并复用。 | ||
func CreateFile(dir, name string) (*os.File, error) { | ||
if dir == "" { | ||
var err error | ||
dir, err = os.Getwd() | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
path := filepath.Join(dir, name) | ||
return os.Create(path) | ||
} |
Oops, something went wrong.