海量用户通讯系统-服务器接收消息2|学习笔记

简介: 快速学习海量用户通讯系统-服务器接收消息2

开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:海量用户通讯系统-服务器接收消息2】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/626/detail/9801


海量用户通讯系统-服务器接收消息2

 

一、反复出现readPkg的原因及解决方法

1、反复出现readPkg的原因:

因为message.go的server这个地方是一直在进for循环的读取,读取包包,读的是-err =conn.Read(buf[:4])这个地方,读的时候它阻塞这个的前提是对方也就是conn一直是有效的,就是大家都持有的一个连接,才会在这里阻塞。也就是conn没有关闭的情况下,才会阻塞。如果说任意一方,不论是客户端还是服务端有一方关闭这个连接,这个就会立即停止。同理如果客户端关闭了conn则,不会阻塞。若不会堵塞就会出现刚才的情况,反复的打出”读取客户端发送的数据...

readPkg err= read pkg header error

Mes= < >”

反复打出这段话的原因是如果不堵塞就读不到东西,读不到东西就报一个错误,又return到下面这里

mes, err := readPkg(conn)

if err != nil {

fmt.PrintIn(“readPkg err=”err)

}

return到这个错误后,又说readPkg err,然后没有进行任何处理,又去进行读取,又返回到上面这个地方,结果发现又读不到东西,把错误抛出,又返回下面那处,就造成了这种现象。

2、解决反复出现现象的方法:

当以下这个代码读的时候

mes, err := readPkg(conn)

if err != nil {

fmt.PrintIn(“readPkg err=”err)

}

已经读错了,有两个方案。一个是双方均退出,就可以做一个判断。判断的方法是

mes, err := readPkg(conn)

if err != nil {

if err == io.EOF

fmt.PrintIn(“客户端退出,服务器端也正常退出“)

return

}     else {

fmt.PrintIn(“readPkg err=”err)

return

}

fmt.PrintIn(“mes=”,mes)

这种判断分两种情况一种是服务端退出了,一种是其他情况,这两种方法均能保证代码没问题。这两个均做完后,EOF那里的原因是没有导io包。将io包导入,如下

package main

import(

“fmt”

“net”

“go_code/chatroom/common/message”

“encoding/binary”

“encoding/json”

“errors’

“io”

将io包导入后,在客户端login这处也先暂时不休眠。休眠测试已经完成了,休眠20秒后会自动关掉,接着测试一下。首先将server端编译一下,然后客户端在编译一下,接着启动一下server端,在启动conn端,接着看效果,假设输入100,密码是tom,接着运行,效果如图

image.png由观察可得它在读取当中,因为现在不进行发送也没有退出,相对于卡在了read那个地方,因为连接都还持有,没有将其关闭,所以这个架构20秒就会关闭。20秒后的提示信息是”readPkg err= read pkg header error”,但是没有将信息打出来。那么这个错误便还不是那个错误,那么证明刚刚的分析还存在一定问题。接着重复刚才的操作,再进行一次,更改原来的代码,如下

package main

import(

“fmt”

“net”

“go_code/chatroom/common/message”

“encoding/binary”

“encoding/json”

—“errors’

“io”

接着在使其运行一次,输入100,密码abc,再次运行观察结果。与原猜想相同,出现了客户端退出,服务器端也退出的提示信息。

3、代码实现

Client/login.go做了修改

//发送了消息本身

-,err = conn.write(data)

if err != nil {

fmt.PrintIn(“conn.write(data) fail”, err)

return

}

//休眠20

time.Sleep(20 * time.Second)

fmt.PrintIn(“休眠了20..”)

//这里还需要处理服务端返回的消息

}

server/main.go

修改//处理客户端的通讯

func process(conn net.conn)

//这里需要延时关闭conn

defer conn.Close()

//循环的客户端发送的信息

for {

//这里我们将数据包,直接封装一个函数readPkg,返回Message, Err

mes,err := readPkg(conn)

if err != nil {

if err == io.EOF {

fmt.PrintIn(“客户端退出,服务器端也退出”)

return

} else

fmt.PrintIn(“readPkg err=”, err)

return

}

}

fmt.PrintIn(“mes=”, mes)

}

}

将读取包的任务封装到了一个函数中readPkg()

func readPkg(conn net.Conn) (mes message.Message, err error) {

buf := make([]byte,8096)

fmt.PrintIn(“读取客户端发送的数据...“)

//conn.Read 在conn没有被关的情况下,才会阻塞

//如果客户端关闭了conn则,就不会阻塞

-,err = conn.Read(buf[:4])

if err != nil {

//err = errors.New(“read pkg header error”)

return

}

//根据buf[:4]转成一个uint32类型

var pkgLen uint32

pkgLen = binary.BigEndian.Uint32(buf[0:4])

//根据pkgLen该消息内容

n, err := conn.Read(buf[:pkgLen])

if n != int(pkgLen) | | err != nil {

//err =errrors.New(“read pkg body errror”)

Return

}

//把pkgLen反序列化成-> message.Message

//技术就是一层窗户纸 &mes

err = json.Unmarshal(buf[:pkgLen], &mes)

if err != nil {

fmt.PrintIn(“json.Unmarsha err”, err)

return

}

return

}

相关文章
|
18天前
|
监控 Java Linux
Linux系统之安装Ward服务器监控工具
【10月更文挑战第17天】Linux系统之安装Ward服务器监控工具
41 5
Linux系统之安装Ward服务器监控工具
|
25天前
|
存储 监控 网络协议
服务器压力测试是一种评估系统在极端条件下的表现和稳定性的技术
【10月更文挑战第11天】服务器压力测试是一种评估系统在极端条件下的表现和稳定性的技术
99 32
|
14天前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
16天前
|
NoSQL Linux PHP
|
24天前
|
网络协议 Ubuntu Linux
gpg从公钥服务器接收失败(gpg: keyserver receive failed: Server indicated a failure)
通过上述步骤,大多数情况下应该能够解决GPG从公钥服务器接收失败的问题。如果问题依旧存在,可能需要进一步调查与公钥服务器相关的更深层次的技术问题,或者考虑在相关社区论坛寻求帮助。
114 1
|
23天前
|
Apache 数据中心 Windows
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
|
23天前
|
域名解析 缓存 网络协议
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
|
6天前
|
弹性计算
阿里云2核16G服务器多少钱一年?亲测价格查询1个月和1小时收费标准
阿里云2核16G服务器提供多种ECS实例规格,内存型r8i实例1年6折优惠价为1901元,按月收费334.19元,按小时收费0.696221元。更多规格及详细报价请访问阿里云ECS页面。
39 9
|
3天前
|
监控 Ubuntu Linux
使用VSCode通过SSH远程登录阿里云Linux服务器异常崩溃
通过 VSCode 的 Remote - SSH 插件远程连接阿里云 Ubuntu 22 服务器时,会因高 CPU 使用率导致连接断开。经排查发现,VSCode 连接根目录 ".." 时会频繁调用"rg"(ripgrep)进行文件搜索,导致 CPU 负载过高。解决方法是将连接目录改为"root"(或其他具体的路径),避免不必要的文件检索,从而恢复正常连接。
|
7天前
|
弹性计算 异构计算
2024年阿里云GPU服务器多少钱1小时?亲测价格查询方法
2024年阿里云GPU服务器每小时收费因实例规格不同而异。可通过阿里云GPU服务器页面选择“按量付费”查看具体价格。例如,NVIDIA A100的gn7e实例为34.742元/小时,NVIDIA A10的gn7i实例为12.710156元/小时。更多详情请访问阿里云官网。
40 2
下一篇
无影云桌面