对于golang 的TCP 编程,服务端就很简单的是listen加accept模式,然后对数据的处理;而客户端就是通过dial创建连接,然后在进行socket的操作

先来看客户端的

首先通过**net.dail()**来创建连接,但是这个时候需要要求目标网络可达,对于不可达网络会出现ERROR

建立完连接之后,可以添加一个IO缓冲
通过**bufio.newreader()**来创建一个reader,通过reader的各种方法来读取数据

然后通过conn的write方法将数据写入到socket里面
conn.write()

在不关闭连接的情况下,通过函数可以一直往socket里面添加数据

package main

import (
   "bufio"
   "fmt"
   "log"
   "net"
   "os"
   "strings"
)

func Client()  {

   conn, err := net.Dial("tcp", "192.168.1.20:8081")//使用dial来实现对服务器的连接

   if err != nil {
      log.Fatal(err)
   }

   //客户端可以发送单行数据,然后就退出
   reader := bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入[终端]   IO缓冲
   //Reader实现了给一个io.Reader接口对象附加缓冲,通过newreader来创建一个具有默认大小缓冲的reader
   for {
      //从终端读取一行用户输入,并准备发送给服务器
      line, err := reader.ReadString('\n')
      //ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。
      //如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误
      if err != nil {
         log.Fatal(err)
      }
      line = strings.Trim(line,"\r\n")
      //返回将s前后端所有cutset包含的utf-8码值都去掉的字符串。

      if line == "exit" {
         fmt.Println("用户退出客户端")
         conn.Close()
         break
      }
      //再将line 发送给 服务器
      conent, err := conn.Write([]byte(line + "\n"))
      //write(b []byte) (n int, err error)
      // write从连接中写数据,n代表的是字节数,写入的类型为byte

      if err != nil {
         log.Fatal(err)
      }
      fmt.Printf("客户端发送了 %d 字节的数据到服务端\n", conent)
   }
}


func main()  {
   Client()
}

再来看看服务端的

服务端采用的是linten+accpet模式

先通过**net.listen()**来监听端口,创建listener

再通过listener的accpet方法创建conn

再通过conn的read方法获取数据进行处理

package main

import (
   "fmt"
   _ "io"
   "log"
   "net" //做网络socket开发时,net包含有网络相关的方法和函数
   "time"
)

func Server()  {
   // Listen函数创建的服务端
   //tcp : 网络协议

   l, err := net.Listen("tcp", "192.168.1.20:8081")
   //返回一个listener
   if err != nil {
      log.Fatal(err)
   }
   defer l.Close()//延时关闭listen
   循环等待客户端访问
   for {

      conn, err := l.Accept()
      //通过监听获取tcp连接   accept返回一个连接conn
      if err != nil {
         log.Fatal(err)
      }
      fmt.Printf("访问客户端信息: con=%v 客户端ip=%v\n", conn, conn.RemoteAddr().String())
       返回远端网络地址
      //    RemoteAddr() Addr
      fmt.Printf("服务器信息=%s\n",conn.LocalAddr().String())

      go handleConnection(conn)
      time.Sleep(time.Second * 10000)
   }
}
//服务端处理从客户端接受的数据
func handleConnection(c net.Conn){
   defer c.Close()//关闭conn

   for {

      //1. 等待客户端通过conn发送信息
      //2. 如果客户端没有wrtie[发送],那么协程就阻塞在这里
      fmt.Printf("服务器在等待客户端%s 发送信息\n", c.RemoteAddr().String())
      buf := make([]byte, 10)
      n, err := c.Read(buf)
      // read从连接中读取数据,写到buf,n代表的是字节数
      // read方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
      if err != nil {
         log.Fatal(err)
         break
      }

      //3. 显示客户端发送的内容到服务器的终端
      fmt.Print(string(buf[:n]))

   }
}

func main()  {
   Server()
}

在启动了服务器后启动客户端,并在客户端输入数据,如下图所示

go语言实现tcp通讯_golang


如果在服务端read的buffer比较小,从客户端发送的数据将会分次在服务端获取。