海量用户通讯信息-服务器接收长度|学习笔记

简介: 快速学习海量用户通讯信息-服务器接收长度

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

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


海量用户通讯信息-服务器接收长度

 

内容介绍:

一、实现功能-完成用户登录

二、思路分析

 

 

一、实现功能-完成用户登录

要求:

先完成指定用户的验证,用户id=100,密码pwd=123456可以登录,其它用户不能登录。

这里需要先说明Message的组成(示意图),并发送一个Message的流程。

示意图为:

image.png客户端:

1、作用:

(1)、接收的输入的id和pwd

(2)、发送id和密码

(3)、接受到服务端返回的结果

(4)、判断是失败还是成功,并显示对应的页面关键的问题是,怎么组织发送的数据

2、消息类型:

(1)、Message[struct]

------------------

Type string

Data string

(2)、LoginMes str{

userld int

userPed string

}

3、发送流程:

(1)、先创建一个Message的结构体

(2)、mes.Type=登录消息类型

(3)、mes.Data=登录消息的内容(序列)

(4)、对mes进行序列化

5)、在网络传输中,最麻烦丢包

先给服务器发送mes的长度(有多少个字节n)

再发送消息本身

服务器:

1、作用

(1)、接收用户id,pwd【goroutine】

(2)、比较

(3)、返回结果

2、消息类型

(1)、Message[struct]

------------------

Type string

Data string

(2)、LoginMes str{

code int//

error string//

}

序列化

3、接收数据的流程:

(1)、接收到客户端发送的长度.len

(2)、根据接收到的长度len,再接收消息本身

(3)、接收时要判断实际接收到的消息内容是否等于len

(4)、如果不相等,就有接错歇息[后面说]

(5)、取到到-反序列化>Message

(6)、取出message.Data(string)-反序列化>LoginMes

(7)、取出loginMes.useridloginMes.userPwd

(8)、这时就可以比较

(9)、根据比较结果,返回Mess

(10)、发送给客户端

Message实现的功能:

实现完成客户端可以发送消息长度,服务器端可以正常收到该长度值。即先完成客户端到服务器,把发过去的长度前期缩到服务器可以接收到。


二、思路分析:

1、先确定消息Message的格式和结构

示意图:

image.png服务器在main.go在端口8889(可随意设置)进行监听,A客户端(main.go)/login.go/utic.go与端口8899进行数据请求连接,当有一个请求连接,服务器开启一个协程,进行与客户端交互,协程通过端口进行相互通讯

Package common消息包建消息结构体。

2、根据上图的分析完成message代码

新建两个文件夹,第一个是commom文件夹,common下再建一个文件夹专门发布消息。在server下新建main.go文件夹(目前至少需要此文件夹)

message.go下输入代码

package common

const(

LoginnesType       =“LoginMes”

LoginresMesType   =“LoginResMes”//登录返回消息

//确定消息常量

type Message struct.{

Type string ‘json:“type”’//消息类型

Data string ‘json:“data”’//消息的内容

}

//定义两个消息..后面需要再增加(目前需要两种消息,一是登录消息,二是登录返回结果消息)

type LoginMes struct {

UserId int ‘json:“userld”’//用户id

UserPwd string‘json:“userpwd”’ //用户密码

UserName string‘json:“username”’ //用户名

}

type LoginResMes struct {

Code int ‘json:“code”’// 返回状态,500 表示该用户未注册 ,200 表示登录成功

error string‘json:“error”’//返回错误信息

}

注:LoginMes、LoginResMes填充到Data,Type string需要描述消息的具体类型,LomgMes是结构体本身的名字。

下一步是发消息,构建message结构体后进行发送

3、完成main.go代码以及login.go代码

(1)、在main.go输入

package main

import(

"fmt"

"net"

//处理和客户端的通讯

func process(conn net.Conn ){

//读取客户端需要的信息

//提示信息

fmt.Println("服务器在8889端口监听....")

listen, err := net.Listen(itcp","0.0.0.0:8889")

Defer listen.close()

if err != nil {

fmt.Println("net.Listen err=", err)

return

//一旦监听成功,就等待客户端来链接服务器

for {

fmt.Println("等待客户端来链接服务器.....”)

conn,err:=listen.Accept()   (注:conn是服务器与客户端之间相互作用重要的媒介)

If err!=nil{

fmt.println(“listen.Accpt err=”,err)

}

//一旦链接成功,则启动一个协程和客户端保持通讯..

go process (conn)

}

(2)、在login.go输入代码

package main

import.(

"fmt"

“encoding/json”

“encoding/binary”

“net”

“go_code/chatroom/common/message”

)

//写一个函数,完成登录

func login(userId int, userPwd string) (err error) {

//下一个就要开始定协议..

// fmt.Printf(" userId = %d userPwd=%s\n", userId, userPwd)

// return nil

//1.链接到服务器

conn, err := net.Dial("tcp","localhost:8889")

if err != nil {

fmt.Println("net.Dial err=", err)

return

//延时关闭

Defer conn.close

//2.准备通过conn发消息给服务

var mes message.nesssage

Mes.type=message.loginmestype

//3.创建一个LoginMes 结构体

var. loginMes message.LoginMes

loginMes.UserId =userId

loginMes.UserPwd =userPwd

//4.将loginMes序列化

data, err := json.Marshal(loginMes)

if err != nil {

fmt.Println("json.Marshal err=", err)

return

} 

// 5. 把data赋给 mes.Data字段

mes.Data =string(data) 此时mes既有data又有type。

// 6.将 mes进行序列化化

data, err =json.Marshal(mes)

 if err != nil {

fmt.Println("json.Marshal err=", err)

return

}

// 7.到这个时候 data就是我们要发送的消息

//7.1 先把 data的长度发送给服务器

conn.write(len(data))此方法是错误的。

在go官网查看net包,type Conn中write实际上发送的是byte切片。

// 先获取到 data的长度->转成一个表示长度的byte切片

Package binary

binary包实现了简单的数字与字节序列的转换以及变长值的编解码,其中一个很重要的方法为ByteOrder,被定义的一个方法为putunit32([]byte,unit32),把具体的数字填到unit32,再给byte切片,那么就会把数字转移给byte切片序列。

var pkglen uint32(此处用unit32是因为发送的数据大)

pkgLen=uint32(len(data))

var buf [4]byte  //定义切片

binary.BigEndian.PutUint32(buf[0:4],pkgLen)

// 发送长度

n,err := conn.Write(buf[:4])

if n != 4ll err != nil{

Fmt.println(“conn.write(buf)fail,err”)

Return

}

Fmt.println(“客户端,发送消息的长度ok

return

}

(3)、上述结束后,服务器等待接收,在main.go添加代码

//这里需要延时关闭conn

Defer conn.close()

//循环的读客户端发送的消息

For{

Buf:=make([]byte,8096)

Fmt.println(“读取客户端发送的数据”)

n,err:=conn.read(buf[:4])

if n != 4 ll err != nil {

fmt.Println("conn.Read err=", err)

Return

}

fmt.Println("读到的buf=",buf[:4])

}

func main() {

相关文章
|
1月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
138 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
1月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
147 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
20天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
192 2
|
1月前
|
网络协议 Ubuntu Linux
gpg从公钥服务器接收失败(gpg: keyserver receive failed: Server indicated a failure)
通过上述步骤,大多数情况下应该能够解决GPG从公钥服务器接收失败的问题。如果问题依旧存在,可能需要进一步调查与公钥服务器相关的更深层次的技术问题,或者考虑在相关社区论坛寻求帮助。
185 1
|
1月前
|
Python
Flask学习笔记(二):基于Flask框架上传图片到服务器端并原名保存
关于如何使用Flask框架上传图片到服务器端并以其原名保存的教程。
75 1
|
1月前
|
Python
Flask学习笔记(三):基于Flask框架上传特征值(相关数据)到服务器端并保存为txt文件
这篇博客文章是关于如何使用Flask框架上传特征值数据到服务器端,并将其保存为txt文件的教程。
31 0
Flask学习笔记(三):基于Flask框架上传特征值(相关数据)到服务器端并保存为txt文件
|
1月前
|
SQL 分布式计算 Hadoop
Hadoop-37 HBase集群 JavaAPI 操作3台云服务器 POM 实现增删改查调用操作 列族信息 扫描全表
Hadoop-37 HBase集群 JavaAPI 操作3台云服务器 POM 实现增删改查调用操作 列族信息 扫描全表
33 3
|
1月前
|
存储 数据采集 分布式计算
Hadoop-17 Flume 介绍与环境配置 实机云服务器测试 分布式日志信息收集 海量数据 实时采集引擎 Source Channel Sink 串行复制负载均衡
Hadoop-17 Flume 介绍与环境配置 实机云服务器测试 分布式日志信息收集 海量数据 实时采集引擎 Source Channel Sink 串行复制负载均衡
44 1
|
21天前
|
缓存 监控 Linux
Python 实时获取Linux服务器信息
Python 实时获取Linux服务器信息
|
8天前
|
机器学习/深度学习 人工智能 弹性计算
什么是阿里云GPU云服务器?GPU服务器优势、使用和租赁费用整理
阿里云GPU云服务器提供强大的GPU算力,适用于深度学习、科学计算、图形可视化和视频处理等多种场景。作为亚太领先的云服务提供商,阿里云的GPU云服务器具备灵活的资源配置、高安全性和易用性,支持多种计费模式,帮助企业高效应对计算密集型任务。