首页 > 编程语言 >go基础-19.网络编程

go基础-19.网络编程

时间:2024-09-24 11:16:43浏览次数:6  
标签:http nil err 19 fmt 编程 Println go main

TCP

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议

如何保证连接可靠呢?(面试常考题)

  1. 三次握手
  2. 四次挥手

服务端

package main

import (
  "fmt"
  "io"
  "net"
)

func main() {
  // 创建tcp的监听地址
  tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
  // tcp监听
  listen, _ := net.ListenTCP("tcp", tcpAddr)
  for {
    // 等待连接
    conn, err := listen.AcceptTCP()
    if err != nil {
      fmt.Println(err)
      break
    }
    // 获取客户端的地址
    fmt.Println(conn.RemoteAddr().String() + " 进来了")
    // 读取客户端传来的数据
    for {
      var buf []byte = make([]byte, 1024)
      n, err := conn.Read(buf)
      // 客户端退出
      if err == io.EOF {
        fmt.Println(conn.RemoteAddr().String() + " 出去了")
        break
      }
      fmt.Println(string(buf[0:n]))
    }

  }

}

客户端

package main

import (
  "fmt"
  "net"
)

func main() {
  conn, _ := net.DialTCP("tcp", nil,
    &net.TCPAddr{
      IP:   net.ParseIP("127.0.0.1"),
      Port: 8080})
  var s string
  for {
    fmt.Scanln(&s)
    if s == "q" {
      break
    }
    conn.Write([]byte(s))
  }

  conn.Close()
}


HTTP

服务端

package main

import "net/http"

// handler
func handler(res http.ResponseWriter, req *http.Request) {
  res.Write([]byte("hello 枫枫"))
}

func main() {
  // 回调函数
  http.HandleFunc("/index", handler)
  // 绑定服务
  http.ListenAndServe(":8080", nil)
}

package main

import (
  "encoding/json"
  "fmt"
  "io"
  "net/http"
  "os"
)

func IndexHandler(res http.ResponseWriter, req *http.Request) {
  switch req.Method {
  case "GET":
    data, err := os.ReadFile("fengfengStudy/37.http/server/index.html")
    if err != nil {
      fmt.Println(data)
    }
    res.Write(data)
    //res.Write([]byte("<h1>hello 枫枫 GET</h1>"))
  case "POST":
    // 获取body数据
    data, err := io.ReadAll(req.Body)
    // 拿请求头
    contentType := req.Header.Get("Content-Type")
    fmt.Println(contentType)
    //switch contentType {
    //case "application/json":
    //
    //}

    if err != nil {
      fmt.Println(data)
    }
    ma := make(map[string]string)
    json.Unmarshal(data, &ma)
    fmt.Println(ma["username"])

    type User struct {
      Username string `json:"username"`
    }
    var user User
    json.Unmarshal(data, &user)
    fmt.Println(user)
    // 设置响应头
    header := res.Header()
    header["token"] = []string{"y1gyf156sdgT%d44hjgj"}
    res.Write([]byte("hello 枫枫 POST"))
  }
}

func main() {
  // 1. 绑定回调
  http.HandleFunc("/index", IndexHandler)
  // 2. 注册服务
  fmt.Println("listen server on http://localhost:8080")
  http.ListenAndServe(":8080", nil)
}

客户端

package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  // 实例化一个http客户端
  client := new(http.Client)
  // 构造请求对象
  req, _ := http.NewRequest("GET", "http://localhost:8080/index", nil)
  // 发请求
  res, _ := client.Do(req)
  // 获取响应
  b, _ := io.ReadAll(res.Body)
  fmt.Println(string(b))

}

RPC

远程过程调用的协议

服务端

package main

import (
  "fmt"
  "net"
  "net/http"
  "net/rpc"
)

type Server struct {
}
type Req struct {
  Num1 int
  Num2 int
}
type Res struct {
  Num int
}

func (s Server) Add(req Req, res *Res) error {
  res.Num = req.Num1 + req.Num2
  return nil
}

func main() {
  // 注册rpc服务
  rpc.Register(new(Server))
  rpc.HandleHTTP()
  listen, err := net.Listen("tcp", ":8080")
  if err != nil {
    fmt.Println(err)
    return
  }
  http.Serve(listen, nil)
}

客户端

package main

import (
  "fmt"
  "net/rpc"
)

type Req struct {
  Num1 int
  Num2 int
}
type Res struct {
  Num int
}

func main() {
  req := Req{1, 2}
  client, err := rpc.DialHTTP("tcp", ":8080")
  if err != nil {
    fmt.Println(err)
    return
  }
  var res Res
  client.Call("Server.Add", req, &res)
  fmt.Println(res)
}

websocket

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

go get github.com/gorilla/websocket

服务端

package main

import (
  "fmt"
  "github.com/gorilla/websocket"
  "net/http"
)

var UP = websocket.Upgrader{
  ReadBufferSize:  1024,
  WriteBufferSize: 1024,
}

func handler(res http.ResponseWriter, req *http.Request) {
  // 服务升级
  conn, err := UP.Upgrade(res, req, nil)
  if err != nil {
    fmt.Println(err)
    return
  }
  for {
    // 消息类型,消息,错误
    t, p, err := conn.ReadMessage()
    if err != nil {
      break
    }
    conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("你说的是:%s吗?", string(p))))
    fmt.Println(t, string(p))
  }
  defer conn.Close()
  fmt.Println("服务关闭")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}


服务端给多个客户端发

package main

import (
  "fmt"
  "github.com/gorilla/websocket"
  "net/http"
)

var UP = websocket.Upgrader{
  ReadBufferSize:  1024,
  WriteBufferSize: 1024,
}

var connLis []*websocket.Conn

func handler(res http.ResponseWriter, req *http.Request) {
  // 服务升级
  conn, err := UP.Upgrade(res, req, nil)
  if err != nil {
    fmt.Println(err)
    return
  }
  connLis = append(connLis, conn)
  for {
    // 消息类型,消息,错误
    t, p, err := conn.ReadMessage()
    if err != nil {
      break
    }
    for index := range connLis {
      connLis[index].WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("你说的是:%s吗?", string(p))))
    }
    fmt.Println(t, string(p))
  }
  defer conn.Close()
  fmt.Println("服务关闭")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}

客户端

package main

import (
  "bufio"
  "fmt"
  "github.com/gorilla/websocket"
  "os"
)

func main() {
  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))
  }
}

func send(conn *websocket.Conn) {
  for {
    reader := bufio.NewReader(os.Stdin)
    l, _, _ := reader.ReadLine()
    conn.WriteMessage(websocket.TextMessage, l)
  }
}


Postman作为客户端

标签:http,nil,err,19,fmt,编程,Println,go,main
From: https://www.cnblogs.com/fengfengzhidao/p/18428759

相关文章

  • go基础-18.反射
    类型判断判断一个变量是否是结构体,切片,mappackagemainimport("fmt""reflect")funcrefType(objany){typeObj:=reflect.TypeOf(obj)fmt.Println(typeObj,typeObj.Kind())//去判断具体的类型switchtypeObj.Kind(){casereflect.Slice:fm......
  • go基础-20.部署
    go项目的部署特别简单,编写完成之后,只需要执行gobuild即可打包为可执行文件注意,这个操作是不同平台不一样的windows下打包就是exe文件,linux下打包就是二进制文件打包命令gobuild打当前目录下的main包,注意,只能有一个main函数的包gobuildxxx.go打当前目录下,xxx.go的......
  • go基础-3.基本数据类型
    go语言的基本数据类型有整数形浮点型复数布尔字符串整数型go语言的整数类型,具体细分有很多varn1uint8=2varn2uint16=2varn3uint32=2varn4uint64=2varn5uint=2varn6int8=2varn7int16=2varn8int32=2varn9int64=2va......
  • go基础-2.变量定义与输入输出
    变量定义标准的变量定义packagemainimport"fmt"funcmain(){//先定义,再赋值varnamestringname="枫枫"fmt.Println(name)//var变量名类型="变量值"varuserNamestring="枫枫"fmt.Println(userName)}如果一个变量定义了......
  • go基础-5.判断语句
    if语句以年龄为例,输入的年龄在某一个区间,就输出对应的提示信息<=0未出生1-18未成年18-35青年>=35中年很明显,这是一个多选一的情况我们有很多中方式来实现中断式packagemainimport"fmt"funcmain(){fmt.Println("请输入你的年龄:")varagei......
  • go基础-4.数组、切片、map
    数组数组(Array)是一种非常常见的数据类型,几乎所有的计算机编程语言中都会用到它数组里的元素必须全部为同一类型,要嘛全部是字符串,要嘛全部是整数声明数组时,必须指定其长度或者大小packagemainimport"fmt"funcmain(){vararray[3]int=[3]int{1,2,3}fmt.Pr......
  • go基础-7.函数和指针
    函数是一段封装了特定功能的可重用代码块,用于执行特定的任务或计算函数接受输入(参数)并产生输出(返回值)函数定义packagemainimport"fmt"//使用func关键字定义一个函数funcsayHello(){fmt.Println("hello")}funcmain(){//函数()调用函数sayHello()}......
  • go基础-6.for循环
    任何编程语言,都会有for循环,它的一般写法是for初始化;条件;操作{}例如求1+2+...+100的和packagemainimport"fmt"funcmain(){varsum=0fori:=0;i<=100;i++{sum+=i}fmt.Println(sum)}for循环的五种变体传统for循环如上死循环每......
  • go基础-8.init函数和defer函数
    init函数init()函数是一个特殊的函数,存在以下特性:不能被其他函数调用,而是在main函数执行之前,自动被调用init函数不能作为参数传入不能有传入参数和返回值一个go文件可以有多个init函数,谁在前面谁就先执行packagemainimport"fmt"funcinit(){fmt.Println("init1"......
  • go基础-11.接口
    接口是一组仅包含方法名、参数、返回值的未具体实现的方法的集合packagemainimport"fmt"//Animal定义一个animal的接口,它有唱,跳,rap的方法typeAnimalinterface{sing()jump()rap()}//Chicken需要全部实现这些接口typeChickenstruct{Namestring}......