zoukankan      html  css  js  c++  java
  • go网络编程应用

    网络编程基础(聊天室)

    服务端

    package main
    
    import (
        "fmt"
        "net"
        "strings"
        "os"
        "log"
    )
    
    
    // 服务器只是中转!
    
    var msgQue = make(chan string, 1000) // 现在处理一个消息队列
    var quitChan = make(chan bool)   // 管理退出消息
    var onlineConns = make(map[string]net.Conn)  // 管理连接
    var logfile *os.File
    var logger *log.Logger
    func ProcessInfo(conn net.Conn) {
        buf := make([]byte, 1024)
        defer func(conn net.Conn) {
            addr := fmt.Sprintf("%s",conn.RemoteAddr())
            delete(onlineConns,addr) // 把断开的链接从字典中去掉
            conn.Close()
            for i := range onlineConns{  // 打印一下
                fmt.Println("online"+i)
            }
            }(conn)
        for {
            numofbyte, err := conn.Read(buf) // 读数据并赋值
            if err != nil {
                break // 报错退出
            }
            if numofbyte != 0 { // 读到了数据长度如果不等于0
    
                msg := string(buf[:numofbyte]) //打印数据,注意之前发的数据因为改的是[]byte,存在未被覆盖的字节信息,所以这里切一下
                msgQue <- msg   // 这里放到channel中
            }
        }
    }
    
    func Checkerror1(err error) {
        if err != nil {
            panic(err)
        }
    }
    
    func doProcessMessage(mesa string){
        content := strings.Split(mesa,"#")  // 把字符串ip序号#消息进行分割
        if len(content) >1 {   //如果有消息
            addr := content[0]
            sendMessage := strings.Join(content[1:],"#")  // 这里为了防止消息中有另外的#
            if conn,ok := onlineConns[addr]; ok{    // 看是前面的ip否在消息队列中
                _, err := conn.Write([]byte(sendMessage))   //如果在的话写入
                if err != nil{
                    fmt.Println("wrong")
                }
            }
        }
    }
    
    func ConsumeMessage() {  // 这个consume用select用来监控两个channel如果quitchan有消息就退出,如果不是就处理消息进行分发
        for {
            select {
            case mssage := <-msgQue: //解析
                doProcessMessage(mssage) // 消息处理,并进行分发
            case <-quitChan:
                break
            }
        }
    }
    
    func main() {
        logfile, err := os.OpenFile("LOG_DIRECORY", os.O_RDWR|os.O_CREATE,0) // 打开文件
        if err != nil{
            fmt.Println("log file create failure!")
            os.Exit(-1)
        }
        defer logfile.Close()
        logger = log.New(logfile,"
    ",log.Ldate|log.Ltime|log.Llongfile)
    
        logger.Println("llkjklj") // 输入log
    
        listen_s, err := net.Listen("tcp", "127.0.0.1:8080") // 开启一个socket
        Checkerror1(err)
        defer listen_s.Close() // 结束关socket
    
        fmt.Println("server is waiting..")
        go ConsumeMessage()
        for {
            conn, err := listen_s.Accept() // socket 接链接
            Checkerror1(err)
            addr := fmt.Sprintf("%s",conn.RemoteAddr()) // 把这个转换一下到string中
            onlineConns[addr] = conn
            go ProcessInfo(conn) // 处理数据
        }
    
    }
    package main
    import (
        "fmt"
        "net"
        "bufio"
        "os"
        "strings"
    )
    
    func MessageSend(conn net.Conn)  {
        var input string
        for {
            reader := bufio.NewReader(os.Stdin)  // 标准输入
            data, _,_ := reader.ReadLine()   // 读到数据到data
            input = string(data)
            if strings.ToUpper(input) == "EXIT" {   // 如果写的是exit就退出
                conn.Close()
                break
            }
            _, err := conn.Write([]byte(input))   // 发消息
            if err != nil {    // 报错退出
                conn.Close()
                fmt.Println("Clinet connect fail")
                break
            }
        }
    }
    
    func Checkerror( err error){
        if err != nil {
            panic(err)
        }
    }
    
    func main(){
        conn, err := net.Dial("tcp","127.0.0.1:8080") // 连接socket
        Checkerror(err)
        defer conn.Close()
        MessageSend(conn)   // 发消息
        buf := make([]byte,1024)
        for {
            _, err := conn.Read(buf)   // 读消息
            if err != nil{
                fmt.Println("exit")
                os.Exit(0)  // 正常退出
            }
            fmt.Println(string(buf))
        }
    }
    客户端
  • 相关阅读:
    Java设计模式
    一个接口多个实现类的Spring注入方式
    Mybatis 中的<![CDATA[ ]]>浅析
    方法内调另一个方法(事务)的探讨
    insertSql语句中的trim标签的使用
    Mybatis-plus的两种分页插件的配置方式
    Mybatis-plus的使用
    spring的IOC,DI及案例详解
    MySQL多表关联数据同时删除
    @Validated和@Valid区别
  • 原文地址:https://www.cnblogs.com/yxi-liu/p/8552181.html
Copyright © 2011-2022 走看看