Go语言实践_实现一(客户端)对一(服务器端)聊天室

一、目的

使用Go语言实现一个服务器端与客户端的聊天室。

软件:Goland,Go1.9

代码仓库地址

二、思路

1,首先启动服务器端,使用listen_socket函数监听IP地址上的客户端连接;

2,启动客户端,并向服务器端发送数据,发送结束后端口阻塞,等待服务器端的消息;

3,服务器端接收到由客户端发送来的消息;

4,服务器端向客户端发送数据,发送结束后;

5,客户端接收到由服务器端发送来的消息,发送结束后端口阻塞,等待客户端的消息;

6,重复步骤2-5;

7,如果服务器端接收到由客户端发送来的“close"消息后,服务器端关闭与客户端的连接,继续等待下一个客户端的连接;

8,客户端关闭,聊天结束。

三、Go代码实现

Sever端

// One-to-one ChatRoom Sever
package main

import (
    "fmt"
    "net"
)

//var ConnMap map[string]*net.TCPConn

func main() {
    listen_socket, err := net.Listen("tcp", "127.0.0.1:8000")  //打开监听接口
    if err != nil { //如果有错误
        fmt.Println("sever error")
    }

    defer listen_socket.Close()  //延迟服务器端关闭
    fmt.Println("sever is wating ....")

    for {
        conn, err := listen_socket.Accept()  //监听客户端的端口
        if err != nil {
            fmt.Println("conn fail ...")
        }
        fmt.Println("connect client successed")  //显示服务器端连接成功

        var msg string  //声明msg为字符串变量

        for {
            //开始接收客户端发过来的消息
            msg = ""  //字符串msg初始为空
            data := make([]byte, 255)  //创建并声明数据变量,为255位
            msg_read, err := conn.Read(data)  //接收由客户端发来的消息,字节赋值给msg_read,err为错误
            if msg_read == 0 || err != nil {  //如果读取的消息为0字节或者有错误
                fmt.Println("err")
            }

            msg_read_str := string(data[0:msg_read])  //将msg_read_str的字节格式转化成字符串形式
            if msg_read_str == "close" {  //如果接收到的客户端消息为close
                conn.Write([]byte("close"))
                break
            }
            //fmt.Println(string(data[0:msg_read]))
            fmt.Println("client say: ", msg_read_str)  //接收客户端发来的信息

            fmt.Printf("say to client: ")  //提示向客户端要说的话
            fmt.Scan(&msg)  //输入服务器端要对客户端说的话
            //conn.Write([]byte("hello client\n"))
            //msg_write := []byte(msg)
            conn.Write([]byte(msg))  //把消息发送给客户端
            //此处造成服务器端的端口堵塞
        }
        fmt.Println("client Close\n")
        conn.Close()  //关闭连接
    }

}

Client端

// One-to-one ChatRoom Client
package main

import (
    "fmt"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8000")
    if err != nil {
        fmt.Println("conn fail...")
    }
    defer conn.Close()
    fmt.Println("connect sever successed")

    var msg string  //声明msg为字符串变量

    for {
        msg = ""  //初始化msg为空值
        fmt.Printf("say to sever: ")
        fmt.Scan(&msg)  //输入客户端向服务器端要发送的消息
        //fmt.Println(msg)
        //msg_write := []byte(msg)
        //conn.Write(msg_write)
        conn.Write([]byte(msg))  //信息转化成字节流形式并向服务器端发送
        //此处造成客户端程序端口堵塞
        //fmt.Println([]byte(msg))

        //等待服务器端发送信息回来
        data := make([]byte, 255)
        msg_read, err := conn.Read(data)
        if msg_read == 0 || err != nil {
            fmt.Println("err")
        }
        msg_read_str := string(data[0:msg_read])
        if msg_read_str == "close" {
            conn.Write([]byte("close"))
            break
        }

        fmt.Println("sever say:", msg_read_str)
    }
    conn.Close()
}

四、小结

  • Write、Read、conn、Scan函数可造成程序的堵塞;
  • 网络中一般是用字节进行数据的传输,所以需要进行格式转换:发送时由字符串转字节;接收时由字节转字符串。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

41. select阻塞一个gorountine上的多个通讯操作 | 厚土Go学习笔记

select 语句可以使得一个 goroutine 在多个通讯操作上等待。select 会阻塞,直到条件分支中的某个分支可以执行,就执行此分支。当多个分支都准备...

38280
来自专栏Danny的专栏

【MyEclipse】——MyEclipse设置注释模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

13530
来自专栏mySoul

客户端的js js脚本的引入 js的解析过程

window对象定义了一些属性,用来指定当前窗口的一些信息。通过该属性的引用,可以获取当前窗口的信息

31680
来自专栏阮一峰的网络日志

JavaScript 运行机制详解:再谈Event Loop

一年前,我写了一篇《什么是 Event Loop?》,谈了我对Event Loop的理解。 上个月,我偶然看到了Philip Roberts的演讲《Help, ...

43370
来自专栏林德熙的博客

win10 uwp 资源字典 资源的key所有的元素都可以定义资源合并资源字典主题资源共享的资源用户控件资源定义

本文主要翻译ResourceDictionary and XAML resource references - UWP app developer ,里面的代码...

13810
来自专栏老马寒门IT

07Vue.js快速入门-Vue路由详解

对于前端来说,其实浏览器配合超级连接就很好的实现了路由功能。但是对于单页面应用来说,浏览器和超级连接的跳转方式已经不能适用, 所以各大框架纷纷给出了单页面应用...

39450
来自专栏java沉淀

Maven、Webx、Velocity学习总结

17930
来自专栏更流畅、简洁的软件开发方式

【自然框架】 页面里的父类——把共用的东东都交给父类,让子类专注于其他。

【类图】 ? 【命名空间】——————————————————【文件截图】 ? ? 可能您会问,不就是弄个父类吗,怎么又是这么复杂呢?这个嘛,听...

23680
来自专栏前端儿

表单多文件上传样式美化 && 支持选中文件后删除相关项

本文根据一个例子,对多文件的上传样式做了一些简单的美化(其实也没怎么美化。。),同时支持选择文件后自定义删除相关的文件,最后再上传

33910
来自专栏林冠宏的技术文章

关于在用curl函数post网页数据时,遇上表单提交 type为submit 类型而且没有name和id时可能遇到的问题及其解决方法

curl函数库实现爬网页内容的链接在 http://www.cnblogs.com/linguanh/p/4292316.html 下面这个是没有name和id...

21370

扫码关注云+社区

领取腾讯云代金券