golang中的socket

简介

网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.socket也具有一个类似打开文件的函数调用:socket(),该函数返回有一个整形的socket描述符,随后的连接建立,数据传输等操作都是通过它实现的

常用的socket类型有两种:流式socket(SOCK_STREAM)和数据报式socket(SOCK_DGRAM)

  • 流式是一种面向连接的socket,针对面向连接的tcp服务应用
  • 数据报式socket是一种无连接的socket,对应于无连接的udp服务应用


listen创建的socket不用于通信,用于监听地址的,accept的socket是用来通信的

read读服务/客户,有返回0,对端关闭和你连接了

函数

server端
Listen函数

func Listen(network, address string) (Listener, error)

network:tcp或者udp
address:ip端口号比如127.0.0.1:9194或者:8005

Listener接口

type Listener interface {
    Accept() (Conn, error)
    Close() error
    Addr() Addr
}

Conn接口

type Conn interface {
   Read(b []byte) (n int, err error)
   Write(b []byte) (n int, err error)
   Close() error
   LocalAddr() Addr
   RemoteAddr() Addr
   SetDeadline(t time.Time) error
   SetReadDeadline(t time.Time) error
   SetWriteDeadline(t time.Time) error
}

tcp服务代码

func main() {

   listener, err := net.Listen("tcp", "0.0.0.0:8183")
   if err != nil {
      fmt.Println("err = ", err)
      return
   }

   //退出前把监听关闭
   defer listener.Close()

   //阻塞等待用户链接
   for {
      conn, err := listener.Accept()
      if err != nil {
         fmt.Println("err = ", err)
         continue
      }
      //接收用户的请求
      //1024缓冲区
      buf := make([]byte, 1024)
      n, err1 := conn.Read(buf)
      if err1 != nil {
         fmt.Println("err1 = ", err1)
         continue
      }

      fmt.Println("buf = ", string(buf[:n]))
      //关闭当前用户的连接
      defer conn.Close()
   }
}

tcp客户端

func main() {

   conn, err := net.Dial("tcp", "127.0.0.1:8183")
   if err != nil {
      fmt.Println("err = ", err)
      return
   }
   defer conn.Close()
   //发送数据
   conn.Write([]byte("are u ok?"))
}

服务端多人

用nc做客户端,telnet做客户端好像会多传东西

func HandleConn(conn net.Conn) {
   //获取客户端的网络地址信息
   addr := conn.RemoteAddr().String()
   fmt.Println("连接成功: ", addr)

   //关闭连接
   defer conn.Close()

   buf := make([]byte, 2048)

   for {
      //读取用户数据,如果客户端关闭了,好像是能发现这边的n是等于0的
      n, err := conn.Read(buf)
      if err != nil {
         //客户端意外关闭,也能发现
         fmt.Println("err = ", err)
         return
      }
      //打印数据
      fmt.Println("数据是: ", string(buf[:n]))
      //看里面多了哪些东西
      fmt.Println("长度是: ", len(string(buf[:n])))
        //因为客户端传递来的有\n
      if "exit" == string(buf[:n-1]) {
         fmt.Println(addr, " exit")
         return
      }

      //把数据转化为大写再发送
      conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
   }
}

func main() {
   listener, err := net.Listen("tcp", "0.0.0.0:8183")
   if err != nil {
      fmt.Println("err = ", err)
      return
   }

   //退出前把监听关闭
   defer listener.Close()

   //阻塞等待用户链接
   for {
      conn, err := listener.Accept()
      if err != nil {
         fmt.Println("err = ", err)
         return
      }
      //处理用户请求
      go HandleConn(conn)
   }
}

可输入回复客户端

func main() {
   conn, err := net.Dial("tcp", "127.0.0.1:8183")
   if err != nil {
      fmt.Println("net.Dial err = ", err)
      return
   }

   //main调用完毕,关闭连接
   defer conn.Close()

   //接收服务器回复的数据
   go func() {
      //从键盘输入内容,给服务器发送内容
      str := make([]byte, 1024)
      for {
         n, err := os.Stdin.Read(str)
         if err != nil {
            fmt.Println("错误信息是: ", err)
            return
         }
         //把输入的内容发给服务器
         conn.Write(str[:n])
      }
   }()

   //切片缓冲
   buf := make([]byte, 1024)
   for {
    //如果服务端关闭和你连接,这边的n是能读取到0的
      n, err := conn.Read(buf)
      if err != nil {
         fmt.Println("错误信息是: ", err)
         return
      }
      fmt.Println(string(buf[:n]))
   }
}

猜你喜欢

转载自blog.csdn.net/ma2595162349/article/details/112911919
今日推荐