一、概述

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

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

二、服务端

package main
import (
    "net"
    "fmt"
    "strings"
)
func handle(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)  
    }
}

三、客户端

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]))
    }
}

四、运行

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

至此,一个完美的多并发服务端就完成了!

最后修改:2017 年 09 月 13 日
喜欢就给我点赞吧