对于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()
}
在启动了服务器后启动客户端,并在客户端输入数据,如下图所示
如果在服务端read的buffer比较小,从客户端发送的数据将会分次在服务端获取。