来自  资质荣誉 2019-09-23 01:42 的文章
当前位置: 澳门太阳娱乐手机登录 > 资质荣誉 > 正文

Golang完成的谈天程序服务端和客商端代码分享,

实现逻辑

1、Golang 版本 1.3

2、实现原理:

  1、主进程建立TCP监听服务,并且初始化一个变量 talkChan := make(map[int]chan string)

  2、当主进程ACCEPT连接请求后,利用go 启动一个协程A去维持和客户端的连接,把taokChan带入到协程里

  3、和客户端建立连接的协程A,发送消息给客户端,使其发送自己的用户信息。

  4、协程A在收到客户端发送的用户信息后,建立一个此用户对应的管道talkChan[uid] = make(chan string)

  5、协程A再启动一个协程A1去专门用来读取客户端发送的消息,并且用来判断是发送给谁的消息,然后把消息放到对应的chan里。

  6、协程A再启动一个协程A2用来读取此用户对应的管道,如果里面有信息,则取出来发送到客户端。

实现逻辑

实现代码

1、Golang 版本  1.3

服务端测试代码:server.go

  1 package main  2   3 import (  4     "fmt"  5     "log"  6     "net"  7     "strconv"  8 )  9  10 func handleConnection(conn net.Conn, talkChan map[int]chan string) { 11     //fmt.Printf("%pn", talkChan)  //用以检查是否是传过来的指针 12  13     /* 14         定义当前用户的uid 15     */ 16     var curUid int 17  18     var err error 19  20     /* 21         定义关闭通道 22     */ 23     var closed = make(chan bool) 24  25     defer func() { 26         fmt.Println("defer do : conn closed") 27         conn.Close() 28         fmt.Printf("delete userid [%v] from talkChan", curUid) 29         delete(talkChan, curUid) 30     }() 31  32     /** 33      * 提示用户设置自己的uid, 如果没设置,则不朝下执行 34      */ 35     for { 36         //提示客户端设置用户id 37         _, err = conn.Write([]byte("请设置用户uid")) 38         if err != nil { 39             return 40         } 41         data := make([]byte, 1024) 42         c, err := conn.Read 43         if err != nil { 44             //closed <- true  //这样会阻塞 | 后面取closed的for循环,没有执行到。 45             return 46         } 47         sUid := string(data[0:c]) 48  49         //转成int类型 50         uid, _ := strconv.Atoi 51         if uid < 1 { 52             continue 53         } 54         curUid = uid 55         talkChan[uid] = make(chan string) 56         //fmt.Println(conn, "have set uid ", uid, "can talk") 57  58         _, err = conn.Write([]byte("have set uid "+sUid+" can talk")) 59         if err != nil { 60             return 61         } 62         break 63     } 64  65     fmt.Println("err 3") 66  67     //当前所有的连接 68     fmt.Println 69  70     //读取客户端传过来的数据 71     go func() { 72         for { 73             //不停的读客户端传过来的数据 74             data := make([]byte, 1024) 75             c, err := conn.Read 76             if err != nil { 77                 fmt.Println("have no client write", err) 78                 closed <- true //这里可以使用 | 因为是用用的go 新开的线程去处理的。 |  即便chan阻塞,后面的也会执行去读 closed 这个chan 79             } 80  81             clientString := string(data[0:c]) 82  83             //将客户端过来的数据,写到相应的chan里 84             if curUid == 3 { 85                 talkChan[4] <- clientString 86             } else { 87                 talkChan[3] <- clientString 88             } 89  90         } 91     }() 92  93     /* 94         从chan 里读出给这个客户端的数据 然后写到该客户端里 95     */ 96     go func() { 97         for { 98             talkString := <-talkChan[curUid] 99             _, err = conn.Write([]byte(talkString))100             if err != nil {101                 closed <- true102             }103         }104     }()105 106     /*107        检查是否已经关闭连接 如果关闭则推出该线程  去执行defer语句108     */109     for {110         if <-closed {111             return112         }113     }114 }115 116 func main() {117 118     /**119     建立监听链接120     */121     ln, err := net.Listen("tcp", "127.0.0.1:6010")122     if err != nil {123         panic124     }125 126     //创建一个管道127 128     //talkChan := map[f]129     talkChan := make(map[int]chan string)130 131     fmt.Printf("%pn", talkChan)132 133     /*134        监听是否有客户端过来的连接请求135     */136     for {137         fmt.Println("wait connect...")138         conn, err := ln.Accept()139         if err != nil {140             log.Fatal("get client connection error: ", err)141         }142 143         go handleConnection(conn, talkChan)144     }145 }

客户端测试代码:client.go

 1 package main 2  3 import ( 4     "fmt" 5     "math/rand" 6     "net" 7 ) 8  9 func main() {10     conn, err := net.Dial("tcp", "127.0.0.1:6010")11     if err != nil {12         panic13     }14 15     fmt.Fprintf(conn, "hello servern")16 17     defer conn.Close()18     go writeFromServer19 20     for {21         var talkContent string22         fmt.Scanln(&talkContent)23 24         if len(talkContent) > 0 {25             _, err = conn.Write([]byte(talkContent))26             if err != nil {27                 fmt.Println("write to server error")28                 return29             }30         }31     }32 }33 34 func connect() {35     conn, err := net.Dial("tcp", "127.0.0.1:6010")36     if err != nil {37         panic38     }39 40     fmt.Fprintf(conn, "hello servern")41 42     defer conn.Close()43     go writeFromServer44 45     for {46         var talkContent string47         fmt.Scanln(&talkContent)48 49         if len(talkContent) > 0 {50             _, err = conn.Write([]byte(talkContent))51             if err != nil {52                 fmt.Println("write to server error")53                 return54             }55         }56     }57 }58 59 func writeFromServer(conn net.Conn) {60     defer conn.Close()61     for {62         data := make([]byte, 1024)63         c, err := conn.Read64         if err != nil {65             fmt.Println("rand", rand.Intn, "have no server write", err)66             return67         }68         fmt.Println(string(data[0:c]) + "n ")69     }70 }

2、实现原理:

  1、主进程建立TCP监听服务,并且初始化一个变量 talkChan := make(map[int]chan string)

  2、当主进程ACCEPT连接请求后,利用go 启动一个协程A去维持和客户端的连接,把taokChan带入到协程里

  3、和客户端建立连接的协程A,发送消息给客户端,使其发送自己的用户信息。

  4、协程A在收到客户端发送的用户信息后,建立一个此用户对应的管道 talkChan[uid] = make(chan string)

  5、协程A再启动一个协程A1去专门用来读取客户端发送的消息,并且用来判断是发送给谁的消息,然后把消息放到对应的chan里。

  6、协程A再启动一个协程A2用来读取此用户对应的管道,如果里面有信息,则取出来发送到客户端。

实现代码

服务端测试代码:server.go

复制代码 代码如下:

package main

import (
    "fmt"
    "log"
    "net"
    "strconv"
)

func handleConnection(conn net.Conn, talkChan map[int]chan string) {
    //fmt.Printf("%pn", talkChan)  //用以检查是否是传过来的指针

    /*
        定义当前用户的uid
    */
    var curUid int

    var err error

    /*
        定义关闭通道
    */
    var closed = make(chan bool)

    defer func() {
        fmt.Println("defer do : conn closed")
        conn.Close()
        fmt.Printf("delete userid [%v] from talkChan", curUid)
        delete(talkChan, curUid)
澳门太阳娱乐在线网址,    }()

    /**
     * 提示用户设置自己的uid, 如果没设置,则不朝下执行
     */
    for {
        //提示客户端设置用户id
        _, err = conn.Write([]byte("请设置用户uid"))
        if err != nil {
            return
        }
        data := make([]byte, 1024)
        c, err := conn.Read(data)
        if err != nil {
            //closed <- true  //这样会阻塞 | 后面取closed的for循环,没有执行到。
            return
        }
        sUid := string(data[0:c])

        //转成int类型
        uid, _ := strconv.Atoi(sUid)
        if uid < 1 {
            continue
        }
        curUid = uid
        talkChan[uid] = make(chan string)
        //fmt.Println(conn, "have set uid ", uid, "can talk")

        _, err = conn.Write([]byte("have set uid "+sUid+" can talk"))
        if err != nil {
            return
        }
        break
    }

    fmt.Println("err 3")

    //当前所有的连接
    fmt.Println(talkChan)

    //读取客户端传过来的数据
    go func() {
        for {
            //不停的读客户端传过来的数据
            data := make([]byte, 1024)
            c, err := conn.Read(data)
            if err != nil {
                fmt.Println("have no client write", err)
                closed <- true //这里可以使用 | 因为是用用的go 新开的线程去处理的。 |  即便chan阻塞,后面的也会执行去读 closed 这个chan
            }

            clientString := string(data[0:c])

            //将客户端过来的数据,写到相应的chan里
            if curUid == 3 {
                talkChan[4] <- clientString
            } else {
                talkChan[3] <- clientString
            }

        }
    }()

    /*
        从chan 里读出给这个客户端的数据 然后写到该客户端里
    */
    go func() {
        for {
            talkString := <-talkChan[curUid]
            _, err = conn.Write([]byte(talkString))
            if err != nil {
                closed <- true
            }
        }
    }()

    /*
       检查是否已经关闭连接 如果关闭则推出该线程  去执行defer语句
    */
    for {
        if <-closed {
            return
        }
    }
}

func main() {

    /**
    建立监听链接
    */
    ln, err := net.Listen("tcp", "127.0.0.1:6010")
    if err != nil {
        panic(err)
    }

    //创建一个管道

    //talkChan := map[f]
    talkChan := make(map[int]chan string)

    fmt.Printf("%pn", talkChan)

    /*
       监听是否有客户端过来的连接请求
    */
    for {
        fmt.Println("wait connect...")
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal("get client connection error: ", err)
        }

        go handleConnection(conn, talkChan)
    }
}

客户端测试代码:client.go

复制代码 代码如下:

package main

import (
    "fmt"
    "math/rand"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:6010")
    if err != nil {
        panic(err)
    }

    fmt.Fprintf(conn, "hello servern")

    defer conn.Close()
    go writeFromServer(conn)

    for {
        var talkContent string
        fmt.Scanln(&talkContent)

        if len(talkContent) > 0 {
            _, err = conn.Write([]byte(talkContent))
            if err != nil {
                fmt.Println("write to server error")
                return
            }
        }
    }
}

func connect() {
    conn, err := net.Dial("tcp", "127.0.0.1:6010")
    if err != nil {
        panic(err)
    }

    fmt.Fprintf(conn, "hello servern")

    defer conn.Close()
    go writeFromServer(conn)

    for {
        var talkContent string
        fmt.Scanln(&talkContent)

        if len(talkContent) > 0 {
            _, err = conn.Write([]byte(talkContent))
            if err != nil {
                fmt.Println("write to server error")
                return
            }
        }
    }
}

func writeFromServer(conn net.Conn) {
    defer conn.Close()
    for {
        data := make([]byte, 1024)
        c, err := conn.Read(data)
        if err != nil {
            fmt.Println("rand", rand.Intn(10), "have no server write", err)
            return
        }
        fmt.Println(string(data[0:c]) + "n ")
    }
}

您可能感兴趣的文章:

  • Golang极简入门教程(一):基本概念
  • 理解Golang中的数组(array)、切片(slice)和map
  • Mac OS系统安装golang教程
  • 在Golang中使用C语言代码实例
  • golang语言中for循环语句用法实例
  • Golang极简入门教程(四):编写第一个项目
  • ubuntu下搭建Go语言(golang)环境
  • golang使用正则表达式解析网页
  • Golang极简入门教程(三):并发支持
  • 利用Go语言实现简单Ping过程的方法

本文由澳门太阳娱乐手机登录发布于 资质荣誉,转载请注明出处:Golang完成的谈天程序服务端和客商端代码分享,

关键词: