2021-01-05 约 1800 字 预计阅读 4 分钟
作业
buf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
)
func main () {
f , err := os . Open ( "a.txt" )
if err != nil {
log . Fatal ( err )
}
defer f . Close ()
r := bufio . NewReaderSize ( f , 10 )
line , _ := r . ReadString ( '\n' )
fmt . Print ( line )
io . Copy ( os . Stdout , f )
}
协程
协程池
pool.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
package main
import (
"log"
"net/http"
"sync"
)
func work ( ch chan string , wg * sync . WaitGroup ) {
for u : = range ch {
resp , err : = http . Get ( u )
if err != nil {
log . Print ( err )
return
}
log . Printf ( " %s : %s " , u , resp . Status )
resp . Body . Close ()
}
wg . Done ()
}
func main () {
wg : = new ( sync . WaitGroup )
wg . Add ( 5 )
taskch : = make ( chan string )
for i : = 0 ; i < 5 ; i ++ {
go work ( taskch , wg )
}
urls : = [] string { "http://www.baidu.com" , "http://www.zhihu.com" }
for _ , url : = range urls {
taskch <- url
}
close ( taskch )
wg . Wait ()
}
pool_step.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
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
// 给定一个url打印url和url的status
// www.baidu.com 200 OK
func printUrl ( url string ) {
resp , err := http . Get ( url )
if err != nil {
log . Print ( err )
return
}
defer resp . Body . Close ()
fmt . Println ( url , resp . Status )
}
func work ( ch chan string , wg * sync . WaitGroup ) {
defer wg . Done ()
for url := range ch {
printUrl ( url )
}
// 等价于
for {
url , ok := <- ch
if ! ok {
break
}
printUrl ( url )
}
}
// 1. 只要不close可以永远发送数据和接受数据
// 2. 如果channel里面没有数据,接收方会阻塞
// 3. 如果没有人正在等待channel的数据,发送方会阻塞
// 4. 从一个close的channle取数据永远不会阻塞,同时获取的是默认值
// 主协程启动一个work协程,同时传递一个channel
// 主协程向channel里面发送一个url
// work协程从channel里面获取url,之后调用printUrl打印url
// 启动3个协程
// 主协程向channel里面发送多个url,发送完毕之后关闭channel
// work协程从channel里面获取url,之后调用printUrl打印url
// work协程不停重复第三条,直到channel关闭
// 创建一个WaitGroup
// 调用Add
// 调用Wait等待work协程结束
func main () {
ch := make ( chan string )
wg := new ( sync . WaitGroup )
//wg.Add(3)
for i := 0 ; i < 3 ; i ++ {
wg . Add ( 1 )
go work ( ch , wg )
}
for i := 0 ; i < 5 ; i ++ {
url := "http://www.baidu.com"
ch <- url
}
close ( ch )
wg . Wait ()
}
客户端
client.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
package main
import (
"fmt"
"io"
"log"
"net"
"os"
)
func main () {
addr := "www.baidu.com:80"
// connection
conn , err := net . Dial ( "tcp" , addr )
if err != nil {
log . Fatal ( err )
}
fmt . Println ( conn . RemoteAddr (). String ())
fmt . Println ( conn . LocalAddr (). String ())
n , err := conn . Write ([] byte ( "GET / HTTP/1.1\r\n\r\n" ))
if err != nil {
log . Fatal ( err )
}
fmt . Println ( "write size" , n )
// buf := make([]byte, 10)
// n, err = conn.Read(buf)
// if err != nil && err != io.EOF {
// log.Fatal(err)
// }
// fmt.Println(string(buf[:n]))
io . Copy ( os . Stdout , conn )
conn . Close ()
}
服务端
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
package main
import (
"log"
"net"
)
var content = ` HTTP / 1.1 200 OK
Date : Sat , 29 Jul 2017 06 : 18 : 23 GMT
Content - Type : text / html
Connection : Keep - Alive
Server : BWS / 1.1
X - UA - Compatible : IE = Edge , chrome = 1
BDPAGETYPE : 3
Set - Cookie : BDSVRTM = 0 ; path =/
< html >
< body >
< h1 style = "color:red" > hello golang </ h1 >
</ body >
</ html >
`
func handleConn ( conn net . Conn ) {
conn . Write ([] byte ( content ))
conn . Close ()
}
func main () {
addr : = ":8021"
listener , err : = net . Listen ( "tcp" , addr )
if err != nil {
log . Fatal ( err )
}
defer listener . Close ()
for {
conn , err : = listener . Accept ()
if err != nil {
log . Fatal ( err )
}
go handleConn ( conn )
}
}
文件服务
file_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
package main
import (
"bufio"
"flag"
"io/ioutil"
"log"
"net"
"os"
"strings"
)
var (
root = flag . String ( "root" , "/" , "root of ftp server data dir" )
)
// client -> GET / home / binggan / a . txt \n
// server -> content of / home / bingan / a . txt
// client -> STORE / home / bingan / a . txt \n content of file EOF
// server -> OK
// client -> LS / home / bingan \n
// server -> content of dir / home / bingan
func handleConn ( conn net . Conn ) {
// 从 conn里面读取一行内容
// 按空格分割指令和文件名
// 打开文件
// 读取内容
// 发送内容
// 关闭连接和文件
defer conn . Close ()
r : = bufio . NewReader ( conn )
line , _ : = r . ReadString ( ' \n ' )
line = strings . TrimSpace ( line )
fields : = strings . Fields ( line )
if len ( fields ) != 2 {
conn . Write ([] byte ( "bad input" ))
return
}
cmd : = fields [ 0 ]
name : = fields [ 1 ]
if cmd == "GET" {
f , err : = os . Open ( name )
if err != nil {
log . Print ( err )
return
}
defer f . Close ()
buf , err : = ioutil . ReadAll ( f )
if err != nil {
log . Print ( err )
return
}
conn . Write ( buf )
} else if cmd == "STORE" {
// 从 r读取文件内容直到err为io . EOF
// 创建 name文件
// 向文件写入数据
// 往 conn写入OK
// 关闭连接和文件
}
}
func main () {
addr : = ":8021"
listener , err : = net . Listen ( "tcp" , addr )
if err != nil {
log . Fatal ( err )
}
defer listener . Close ()
for {
conn , err : = listener . Accept ()
if err != nil {
log . Fatal ( err )
}
go handleConn ( conn )
}
}
聊天服务
chat_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
package main
import (
"bufio"
"log"
"net"
"strings"
)
var globalRoom * Room = NewRoom ()
type Room struct {
users map [ string ] net . Conn
}
func NewRoom () * Room {
return & Room {
users : make ( map [ string ] net . Conn ),
}
}
func ( r * Room ) Join ( user string , conn net . Conn ) {
conn , ok : = r . users [ user ]
if ok {
r . Leave ( user )
}
r . users [ user ] = conn
}
func ( r * Room ) Leave ( user string ) {
// 关闭连接
// 从 users里面删掉
}
func ( r * Room ) Broadcast ( user string , msg string ) {
// 遍历所有的用户,发送消息
}
// client -> binggan 123456
// client -> hello golang
// client -> close
// 接收新的连接
// 验证用户的账号和密码
// 等待用户输入
// 向所有在线的用户广播用户的输入
func handleConn ( conn net . Conn ) {
defer conn . Close ()
r : = bufio . NewReader ( conn )
line , _ : = r . ReadString ( ' \n ' )
line = strings . TrimSpace ( line )
fields : = strings . Fields ( line )
if len ( fields ) != 2 {
conn . Write ([] byte ( "bad input" ))
return
}
user : = fields [ 0 ]
password : = fields [ 1 ]
if password != "123456" {
return
}
// join用户
for {
// 获取用户输入
// broadcast
}
// leave用户
}
func main () {
addr : = ":8021"
listener , err : = net . Listen ( "tcp" , addr )
if err != nil {
log . Fatal ( err )
}
defer listener . Close ()
for {
conn , err : = listener . Accept ()
if err != nil {
log . Fatal ( err )
}
go handleConn ( conn )
}
}
总结
homework