Golang网络编程(二):并发Server

一、概述

上一篇实现了一个server和client通信,完成了小写转大写的功能,但是是一个单任务式的响应:客户端发送连接接收响应,程序结束;服务端则接收数据响应数据也结束!就实际需要而言,并没有很大的用处,所以现在我们就给客户端和服务端添加上并发功能。

逻辑其实很简单,就是利用golang的gorutine,一旦来新的连接,就开启一个gorutine去处理,然后响应,直到客户端关闭连接。

二、服务端

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
package main

import (
"net"
"fmt"
"strings"
)

func (conn net.Conn){
defer conn.Close()
fmt.Println("Connect :", conn.RemoteAddr())

for {
//只要客户端没有断开连接,一直保持连接,读取数据
data := make([]byte, 2048)
n, err := conn.Read(data)
//数据长度为0表示客户端连接已经断开
if n == 0{
fmt.Printf("%s has disconnect
", conn.RemoteAddr())
break
}
if err != nil{
fmt.Println(err)
continue
}
fmt.Printf("Receive data [%s] from [%s]
", string(data[:n]), conn.RemoteAddr())
//转大写
rspData := strings.ToUpper(string(data[:n]))
_, err = conn.Write([]byte(rspData))
if err != nil{
fmt.Println(err)
continue
}
}

}

func main(){
listener, err := net.Listen("tcp", ":8899")
if err != nil{
fmt.Println(err)
return
}
fmt.Println("Start listen localhost:8899")

for {
//开始循环接收客户端连接
conn, err := listener.Accept()
if err != nil{
fmt.Println(err)
return
}
//一旦收到客户端连接,开启一个新的gorutine去处理这个连接
go handle(conn)
}
}

三、客户端

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
import (
"net"
"fmt"
)

func main(){
conn, err := net.Dial("tcp", ":8899") //连接服务端
if err != nil{
fmt.Println(err)
return
}
fmt.Println("Connect to localhost:8899 success")
defer conn.Close()

for{
//一直循环读入用户数据,发送到服务端处理
fmt.Print("Please input send data :")
var a string
fmt.Scan(&a)
if a == "exit"{break} //添加一个退出机制,用户输入exit,退出

_, err := conn.Write([]byte(a))
if err != nil{
fmt.Println(err)
return
}

data := make([]byte, 2048)
n, err := conn.Read(data)
if err != nil{
fmt.Println(err)
continue
}
fmt.Println("Response data :", string(data[:n]))
}

}

四、运行

此时,我们开启一个服务端,开启两个客户端进行测试:
服务端:
VCpkcQ.png
客户端:
VCpVns.png
VCpAXj.png

原文:大专栏  Golang网络编程(二):并发Server

相关文章
相关标签/搜索