【Java转Go】快速上手学习笔记(六)之网络编程篇一

目录

  • TCP
    • 一个简单案例
      • server.go 服务端
      • client.go 客户端
  • HTTP
      • server.go 服务端
      • client.go 客户端
  • RPC
    • 一个很简单的示例
      • server.go 服务端
      • client.go 客户端
  • WebSocket
      • server.go 服务端
      • client.go 客户端
  • 完整代码
    • server.go 服务端
    • client.go 客户端

go往期文章笔记:

【Java转Go】快速上手学习笔记(一)之环境安装篇

【Java转Go】快速上手学习笔记(二)之基础篇一

【Java转Go】快速上手学习笔记(三)之基础篇二

【Java转Go】快速上手学习笔记(四)之基础篇三

【Java转Go】快速上手学习笔记(五)之Gorm篇


这篇记的是网络编程相关的笔记。

TCP

开启服务端,监听连接的请求。示意图:
在这里插入图片描述

服务端:启动后,监听连接过来的客户端,每连接过来一个客户端,开启一个协程去和客户端进行交互(一个协程代表一个客户端)

客户端:根据服务端的IP和端口号去访问服务端,连接成功后可以向服务端发送消息。

连接的时候通过IP和端口号去连接,但是和客户端进行交流的是协程。

一个简单案例

创建两个文件夹,一个是server、一个是client,然后两个文件夹里面分别创建 server.go、client.go 文件,如下图:

在这里插入图片描述

server.go 服务端

package mainimport ("fmt""io""net"
)// tcp处理客户端发送过来的信息
func tcpHandler(conn net.Conn) {defer conn.Close()for {var buf []byte = make([]byte, 1024)// 等待客户端通过conn发送信息,如果客户端没有wrtie[发送],那么协程就阻塞在这里n, err := conn.Read(buf)if err == io.EOF {fmt.Println(conn.RemoteAddr().String() + " 退出连接")break}// 客户端发送的内容显示到服务器的终端fmt.Print(string(buf[:n]))}
}func main() {TCP服务端()
}func TCP服务端() {fmt.Println("服务器开始监听")listen, err := net.Listen("tcp", "0.0.0.0:8888")if err != nil {fmt.Println(err)return}defer listen.Close()for { // 循环等待客户端来连接conn, err := listen.Accept()if err != nil {fmt.Println(err)} else {fmt.Printf("客户端 %v 连接成功\n", conn.RemoteAddr().String())}// 这里开启协程go tcpHandler(conn)}
}

client.go 客户端

package mainimport ("fmt""net"
)func main() {TCP客户端()
}func TCP客户端() {conn, err := net.Dial("tcp", "127.0.0.1:8888")if err != nil {fmt.Println(err)return}defer conn.Close()fmt.Println(conn.RemoteAddr().String(), "连接成功")var s stringfor { // 循环输入,给服务端发送消息// 从终端读取用户输入,并发送给服务器fmt.Scanln(&s)if s == "exit" {fmt.Println(conn.RemoteAddr().String(), "退出连接")break}conn.Write([]byte(s + "\r\n")) // 发送给服务端}
}

写好之后,我们先启动服务端,然后再启动客户端。在客户端里面输入消息发送给服务端,服务端接收后要将消息显示出来。

在这里插入图片描述
在这里插入图片描述

客户端输入 exit 时,退出程序,关闭了连接,服务端也显示这个客户端已经退出了连接。
在这里插入图片描述
在这里插入图片描述

HTTP

server.go 服务端

// http处理请求
func httpHandler(res http.ResponseWriter, req *http.Request) {switch req.Method {case "GET":fmt.Println("这里是get请求")res.Write([]byte("这里是get请求"))case "POST":defer req.Body.Close()// 1、 请求类型是aplication/x-www-form-urlencode时解析form数据//req.ParseForm()//fmt.Println(req.PostForm) //打印form数数据//fmt.Println(req.PostForm.Get("username"), req.PostForm.Get("password"))// 2、请求类型是application/json时从req.Body读取数据b, err := io.ReadAll(req.Body)if err != nil {fmt.Println("获取请求数据错误", err)return}fmt.Println(string(b))result := `{"code":0,"message":"ok","data":{}}` // 请求成功,返回数据res.Write([]byte(result))}
}func main() {HTTP服务端()
}func HTTP服务端() {http.HandleFunc("/index", httpHandler) // 回调函数fmt.Println("http://localhost:8080")http.ListenAndServe(":8080", nil) // 绑定服务
}

client.go 客户端

func main() {HTTP客户端()
}func HTTP客户端() {data := `{"username":"符华","password":"123456"}`//resp, err := http.Get("http://localhost:8080/index")resp, err := http.Post("http://localhost:8080/index", "application/json", strings.NewReader(data))//resp, err := http.PostForm("http://localhost:8080/index", url.Values{"username": {"符华"}, "password": {"123456"}})if err != nil {fmt.Println("请求错误", err)return}defer resp.Body.Close()b, err := io.ReadAll(resp.Body)if err != nil {fmt.Println("获取返回数据错误", err)return}fmt.Println(string(b))
}

RPC

一个很简单的示例

server.go 服务端

import ("net""net/http""net/rpc"
)type Server struct{}
type Req struct {Num1 intNum2 int
}
type Res struct {Num int
}func (s Server) Add(req Req, res *Res) error {res.Num = req.Num1 + req.Num2return nil
}func RPC服务端() {// 注册rpc服务rpc.Register(new(Server))rpc.HandleHTTP()listen, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println(err)return}http.Serve(listen, nil)
}func main() {RPC服务端()
}

client.go 客户端

import ("fmt""net""net/rpc"
)type Req struct {Num1 intNum2 int
}
type Res struct {Num int
}func RPC客户端() {req := Req{1, 2}client, err := rpc.DialHTTP("tcp", ":8080")if err != nil {fmt.Println(err)return}var res Resclient.Call("Server.Add", req, &res)fmt.Println(res)
}func main() {RPC客户端()
}

WebSocket

websocket是socket连接和http协议的结合体,可以实现网页和服务端的长连接。

要使用websocket我们要先去下载依赖

go get github.com/gorilla/websocket

server.go 服务端

// websocke 连接的升级器。升级器是一个http.HandlerFunc,它将HTTP连接升级为WebSocket连接
var UP = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,
}
var conns []*websocket.Conn // 客户端连接切片,存储所有的客户端连接// websocket处理请求
func websocketHandler(res http.ResponseWriter, req *http.Request) {conn, err := UP.Upgrade(res, req, nil) // 服务升级if err != nil {fmt.Println(err)return}defer conn.Close()conns = append(conns, conn)for {// 消息类型,消息,错误t, p, err := conn.ReadMessage()if err != nil {break}for index := range conns {conns[index].WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("你说的是:%s吗?", string(p))))}fmt.Println(t, string(p))}fmt.Println("服务关闭")
}func websocket服务端() {http.HandleFunc("/", websocketHandler)http.ListenAndServe(":8080", nil)
}

client.go 客户端

// websocket 发送消息
func send(conn *websocket.Conn) {for {reader := bufio.NewReader(os.Stdin)l, _, _ := reader.ReadLine()conn.WriteMessage(websocket.TextMessage, l)}
}func websocket客户端() {dl := websocket.Dialer{}conn, _, err := dl.Dial("ws://127.0.0.1:8080", nil)if err != nil {fmt.Println(err)return}go send(conn)for {t, p, err := conn.ReadMessage()if err != nil {break}fmt.Println(t, string(p))}
}

完整代码

server.go 服务端

package mainimport ("fmt""github.com/gorilla/websocket""io""net""net/http""net/rpc"
)// tcp处理客户端发送过来的信息
func tcpHandler(conn net.Conn) {defer conn.Close()for {var buf []byte = make([]byte, 1024)// 等待客户端通过conn发送信息,如果客户端没有wrtie[发送],那么协程就阻塞在这里n, err := conn.Read(buf)if err == io.EOF {fmt.Println(conn.RemoteAddr().String() + " 退出连接")break}// 客户端发送的内容显示到服务器的终端fmt.Print(string(buf[:n]))}
}// http处理请求
func httpHandler(res http.ResponseWriter, req *http.Request) {switch req.Method {case "GET":fmt.Println("这里是get请求")res.Write([]byte("这里是get请求"))case "POST":defer req.Body.Close()// 1、 请求类型是aplication/x-www-form-urlencode时解析form数据//req.ParseForm()//fmt.Println(req.PostForm) //打印form数数据//fmt.Println(req.PostForm.Get("username"), req.PostForm.Get("password"))// 2、请求类型是application/json时从req.Body读取数据b, err := io.ReadAll(req.Body)if err != nil {fmt.Println("获取请求数据错误", err)return}fmt.Println(string(b))result := `{"code":0,"message":"ok","data":{}}` // 请求成功,返回数据res.Write([]byte(result))}
}// RPC
type Server struct{}
type Req struct {Num1 intNum2 int
}
type Res struct {Num int
}func (s Server) Add(req Req, res *Res) error {res.Num = req.Num1 + req.Num2return nil
}// websocke 连接的升级器。升级器是一个http.HandlerFunc,它将HTTP连接升级为WebSocket连接
var UP = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,
}
var conns []*websocket.Conn // 客户端连接切片,存储所有的客户端连接// websocket处理请求
func websocketHandler(res http.ResponseWriter, req *http.Request) {conn, err := UP.Upgrade(res, req, nil) // 服务升级if err != nil {fmt.Println(err)return}defer conn.Close()conns = append(conns, conn)for {// 消息类型,消息,错误t, p, err := conn.ReadMessage()if err != nil {break}for index := range conns {conns[index].WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("你说的是:%s吗?", string(p))))}fmt.Println(t, string(p))}fmt.Println("服务关闭")
}func main() {//TCP服务端()//HTTP服务端()//RPC服务端()websocket服务端()
}func TCP服务端() {fmt.Println("服务器开始监听")listen, err := net.Listen("tcp", "0.0.0.0:8080")if err != nil {fmt.Println(err)return}defer listen.Close()for { // 循环等待客户端来连接conn, err := listen.Accept()if err != nil {fmt.Println(err)} else {fmt.Printf("客户端 %v 连接成功\n", conn.RemoteAddr().String())}// 这里开启协程go tcpHandler(conn)}
}func HTTP服务端() {http.HandleFunc("/index", httpHandler) // 回调函数fmt.Println("http://localhost:8080")http.ListenAndServe(":8080", nil) // 绑定服务
}func RPC服务端() {// 注册rpc服务rpc.Register(new(Server))rpc.HandleHTTP()listen, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println(err)return}http.Serve(listen, nil)
}func websocket服务端() {http.HandleFunc("/", websocketHandler)http.ListenAndServe(":8080", nil)
}

client.go 客户端

package mainimport ("bufio""fmt""github.com/gorilla/websocket""io""net""net/http""net/rpc""os""strings"
)func main() {//TCP客户端()//HTTP客户端()//RPC客户端()websocket客户端()
}func TCP客户端() {conn, err := net.Dial("tcp", "127.0.0.1:8080")if err != nil {fmt.Println(err)return}defer conn.Close()fmt.Println(conn.RemoteAddr().String(), "连接成功")var s stringfor { // 循环输入,给服务端发送消息// 从终端读取用户输入,并发送给服务器fmt.Scanln(&s)if s == "exit" {fmt.Println(conn.RemoteAddr().String(), "退出连接")break}conn.Write([]byte(s + "\r\n")) // 发送给服务端}
}func HTTP客户端() {data := `{"username":"符华","password":"123456"}`//resp, err := http.Get("http://localhost:8080/index")resp, err := http.Post("http://localhost:8080/index", "application/json", strings.NewReader(data))//resp, err := http.PostForm("http://localhost:8080/index", url.Values{"username": {"符华"}, "password": {"123456"}})if err != nil {fmt.Println("请求错误", err)return}defer resp.Body.Close()b, err := io.ReadAll(resp.Body)if err != nil {fmt.Println("获取返回数据错误", err)return}fmt.Println(string(b))
}// RPC
type Req struct {Num1 intNum2 int
}
type Res struct {Num int
}func RPC客户端() {req := Req{1, 2}client, err := rpc.DialHTTP("tcp", ":8080")if err != nil {fmt.Println(err)return}var res Resclient.Call("Server.Add", req, &res)fmt.Println(res)
}// websocket 发送消息
func send(conn *websocket.Conn) {for {reader := bufio.NewReader(os.Stdin)l, _, _ := reader.ReadLine()conn.WriteMessage(websocket.TextMessage, l)}
}func websocket客户端() {dl := websocket.Dialer{}conn, _, err := dl.Dial("ws://127.0.0.1:8080", nil)if err != nil {fmt.Println(err)return}go send(conn)for {t, p, err := conn.ReadMessage()if err != nil {break}fmt.Println(t, string(p))}
}

ok,以上就是本篇笔记的全部内容了,就是一些简单的使用示例,关于理论概念的东西我没有记,因为太多了,不知道要怎么整理才能说明白说清楚,反正就是这么用的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/111308.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(笔记四)利用opencv识别标记视频中的目标

预操作: 通过cv2将视频的某一帧图片转为HSV模式,并通过鼠标获取对应区域目标的HSV值,用于后续的目标识别阈值区间的选取 img cv.imread(r"D:\data\123.png") img cv.cvtColor(img, cv.COLOR_BGR2HSV) plt.figure(1), plt.imshow…

开始MySQL之路——MySQL 事务(详解分析)

MySQL 事务概述 MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等&#xf…

打造互动体验:品牌 DTC 如何转变其私域战略

越来越多的品牌公司选择采用DTC 模式与消费者进行互动,而非仅仅销售产品。通过与消费者建立紧密联系,DTC模式不仅可以提供更具成本效益的规模扩张方式,还能够控制品牌体验、获取宝贵的第一方数据并提升盈利能力。然而DTC模式的经济模型比许多…

Docker创建Consul并添加权限控制

一、部署Consul 1、拉取镜像&#xff1a; docker pull consul:<consul-version> 2、运行 docker run --name consul1 -p 8300:8300/tcp -p 8301:8301/tcp -p 8301:8301/udp -p 8302:8302/tcp -p 8302:8302/udp -p 8500:8500 -p 8600:8600/tcp -p 8600:8600/udp -v /h…

数据结构——栈

栈 栈的理解 咱们先不管栈的数据结构什么&#xff0c;先了解栈是什么&#xff0c;栈就像一个桶一样&#xff0c;你先放进去的东西&#xff0c;被后放进的的东西压着&#xff0c;那么就需要把后放进行的东西拿出才能拿出来先放进去的东西&#xff0c;如图1&#xff0c;就像图1中…

Android Studio调试出现错误时,无法定位错误信息解决办法

做项目时运行项目会出现问题&#xff0c;但是找不到具体位置&#xff0c;如下图所示&#xff1a;感觉是不是很懵逼~&#xff0c;Log也没有显示是哪里的问题 解决方案&#xff0c;在右侧导航栏中选择Gradle——app——build&#xff0c;然后点击运行 运行结果如下&#xff0c;很…

C#: Json序列化和反序列化,集合为什么多出来一些元素?

如下面的例子&#xff0c;很容易看出问题&#xff1a; 如果类本身的无参构造函数&#xff0c; 就添加了一些元素&#xff0c;序列化&#xff0c;再反序列化&#xff0c;会导致元素增加。 如果要避免&#xff0c;必须添加&#xff1a; new JsonSerializerSettings() { Object…

SQL语法与DDL语句的使用

文章目录 前言一、SQL通用语法二、DDL语句1、DDL功能介绍2、DDL语句对数据库操作&#xff08;1&#xff09;查询所有数据库&#xff08;2&#xff09;查询当前数据库&#xff08;3&#xff09;创建数据库&#xff08;4&#xff09;删除数据库&#xff08;5&#xff09;切换数据…

17 django框架(中)视图|模板

文章目录 框架介绍模型类视图视图的功能页面重定向 视图函数的使用url匹配过程错误视图补充 捕获url参数类型介绍 普通登录案例&#xff08;前情准备&#xff09;HttpReqeust 对象HttpResponse 对象QueryDict 对象&#xff08;即GET POST &#xff09;总结 ajaxajax的登录样例 …

C# task多线程创建,暂停,继续,结束使用

1、多线程任务创建 private void button1_Click(object sender, EventArgs e) //创建线程{CancellationToken cancellationToken tokensource.Token;Task.Run(() > //模拟耗时任务{for (int i 0; i < 100; i){if (cancellationToken.IsCancellationRequested){return;…

开发卡牌gamefi游戏需要多少钱?

卡牌游戏作为一种受欢迎的游戏形式&#xff0c;吸引了众多开发者的关注。然而&#xff0c;开发一款成功的卡牌游戏需要全面考虑多个方面的因素&#xff0c;其中之一就是资金投入。本文将从专业性和投入回报的角度&#xff0c;探讨开发一款卡牌游戏所需的资金投入。 一、专业性的…

Ansible项目实战管理/了解项目环境/项目管理

一&#xff0c;项目环境 1.项目基础 项目过程 调研阶段 设计阶段 开发阶段 测试阶段 运营阶段 2.项目环境 个人开发环境 公司开发环境 项目测试环境 项目预发布环境 灰度环境&#xff1a;本身是生产环境&#xff0c;安装项目规划&#xff0c;最终所有的生产环境都发…

最新Nmap入门技术

点击星标&#xff0c;即时接收最新推文 本文选自《web安全攻防渗透测试实战指南&#xff08;第2版&#xff09;》 点击图片五折购书 Nmap详解 Nmap&#xff08;Network Mapper&#xff0c;网络映射器&#xff09;是一款开放源代码的网络探测和安全审核工具。它被设计用来快速扫…

Linux操作系统--linux概述

1.Linux概述 Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff08;OS&#xff09;。简单的说就是一种操作系统。在日常中常见的操作系统有一下三种: 2.linux起源和背景 (1).linux的诞生 linux操作系统是由李纳斯托瓦兹&#xf…

小研究 - J2EE 应用服务器的软件老化测试研究

软件老化现象是影响软件可靠性的重要因素&#xff0c;长期运行的软件系统存在软件老化现象&#xff0c;这将影响整个业务系统的正常运行&#xff0c;给企事业单位带来无可估量的经济损失。软件老化出现的主要原因是操作系统资源消耗殆尽&#xff0c;导致应用系统的性能下降甚至…

读书笔记——《万物有灵》

前言 上一本书是《走出荒野》&#xff0c;太平洋步道女王提到了这本书《万物有灵》&#xff0c;她同样是看一点撕一点的阅读。我想&#xff0c;在她穿越山河森林&#xff0c;听见鸟鸣溪流的旅行过程中&#xff0c;是不是看这本描写动物有如何聪明的书——《万物有灵》&#xf…

YOLOv5引入FasterNet主干网络,目标检测速度提升明显

目录 一、背景介绍1.1 目标检测算法简介1.2 YOLOv5简介及发展历程 二、主干网络选择的重要性2.1 主干网络在目标检测中的作用2.2 YOLOv5使用的默认主干网络 三、FasterNet简介与原理解析3.1 FasterNet概述3.2 FasterNet的网络结构3.2.1 基础网络模块3.2.2 快速特征融合模块3.2.…

docker network

docker network create <network>docker network connect <network> <container>docker network inspect <network>使用这个地址作为host即可 TODO&#xff1a;添加docker-compose

最新企业网盘产品推荐榜发布

随着数字化发展&#xff0c;传统的文化存储方式已无法跟上企业发展的步伐。云存储的出现为企业提供了新的文件管理存储模式。企业网盘作为云存储的代表性工具&#xff0c;被越来越多的企业所青睐。那么在众多企业网盘产品中&#xff0c;企业该如何找到合适的企业网盘呢&#xf…

idea上利用JDBC连接MySQL数据库(8.1.0版)

1.了解jdbc概念 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API&#xff0c;可以为多种 关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准&#xff0c;据此可以构建 更高级的工具和接口&#…