2022/02/15 又熬夜了又熬夜了....
今天主要学习了go的网络变成,可以把第一段代码视为笔记,第二段代码块视为demo
//1. client
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
//1.用dial, 链接指定的地址,端口号
conn, err := net.Dial("tcp", "192.168.1.103:8888")
if err != nil {
fmt.Println("客户端链接失败,直接退出")
return
}
//2.链接成功,延时关闭conn
defer conn.Close()
//3.循环向客户端发送数据
var reader *bufio.Reader
for {
reader = bufio.NewReader(os.Stdin) //从键盘获取字符
//从reader中获取一行用户输入的字符串发送给服务器
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("从reader读取字符串错误: ", err)
}
line = strings.TrimSpace(line)
if line == "quit" {
return
}
//4.将获取到的string类型的line 转换字节切片写入conn中
n, err := conn.Write([]byte(line))
if err != nil {
fmt.Println("写入conn错误: ", err)
}
fmt.Printf("客户端成功发送了%d个数据...\n", n)
}
}
//1.server
package main
import (
"fmt"
"net"
"strings"
)
func process(conn net.Conn) {
//4.延时关闭conn
defer conn.Close()
//5.开始接收数据打印数据
for {
buf := make([]byte, 1024) //缓存信息切片
fmt.Println("等待客户端输入数据")
n, err := conn.Read(buf) //读取conn中的数据到buf中
if err != nil { //读取有错误,超时或者客户端退出
fmt.Println("读取有错误,超时或者客户端退出")
//关闭协程
return
}
//显示收到的客户端的信息,打印到终端,如果是quit,就退出
fmt.Print(string(buf[:n]))
buff := strings.TrimSpace(string(buf[:n]))
if buff == "quit" {
fmt.Println("客户端退出程序!")
return
} else {
fmt.Println("客户端发送的消息: ", buff)
}
/*
这里需要说明一下,为什么是读取buf[:n],而不是buf呢
返回的n是有效字符的个数,buf[:n]里面就是我们客户端输入的东西
如果是buf,就会把我们的1024个字节空间没有字符的也会输出
demo:
假设这是buf的值 hello0000
buf[:n] hello
buf hello0000
当然内存中并不一定是0,都是垃圾值,没必要读
*/
}
}
func main() {
//1.先listen监听本地接口
listen, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("监听发生错误, err= ", err)
return //监听错误就没有必要进行下面的东西了
}
//2.延时关闭listen
defer listen.Close()
//3.等待客户端连接,开始循环Accept()
for {
fmt.Println("循环等待客户端链接...")
conn, err := listen.Accept()
if err != nil { //有客户端链接错误,但是不影响其他客户端
fmt.Println("Accept 错误")
} else { //链接成功就打印客户端的信息,ip地址
fmt.Println("链接成功的客户端信息: ", conn.RemoteAddr().String())
}
//链接成功就开启一个协程,为客户端服务
go process(conn)
}
}
=========================================================================
//2.client
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "192.168.1.103:8888")
if err != nil {
fmt.Println("client dial err = ", err)
return
}
defer conn.Close()
fmt.Println("client dial success , conn = ", conn)
//1.客户端可以发送单行数据,然后就退出
reader := bufio.NewReader(os.Stdin) //Stdin、Stdout和Stderr是指向标准输入、标准输出、标准错误输出的文件描述符。
//从终端读取一行用户的输入并准备发送给服务器
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("reader string err", err)
}
fmt.Println("input your message...")
//2.在控制台输入一段话,发送到服务器终端打印
n, err := conn.Write([]byte(line))
if err != nil {
fmt.Println("conn.Write err = ", err)
}
fmt.Printf("client send %d byte, quit\n", n)
}
//2.server
package main
import (
"fmt"
"net" //做网络socket变成,net包满足所有我们需要的方法和函数
)
func process(conn net.Conn) {
//这里我们循环的接收客户端发送的数据
defer conn.Close() //处理完一定要关闭
for {
buf := make([]byte, 1024)
//1.等待客户端通过conn发送信息
//2.如果客户端没有write[发送],那么协程就阻塞在这里
fmt.Printf("server waiting %s send message...", conn.RemoteAddr().String())
n, err := conn.Read(buf) //从conn读取
if err != nil { //超时,链接断开,协程就会退出
fmt.Println("server read err: ", err)
return //读的时候有可能出错,超时或者客户端关闭,就结束协程
}
//3.显示客户端发送的内容到服务器的终端
fmt.Print(string(buf[:n])) //buf[:n]是管道里面真正的东西
}
}
func main() {
fmt.Println("服务器开始监听....")
//1.这里的tcp表示使用的网络协议是tcp
//2. 0.0.0.0:8888 表示在本地监听8888端口
listen, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("listen err = ", err)
return
}
defer listen.Close() //延时关闭
fmt.Printf("listen = %v\n", listen)
//循环等待客户端来连接我
for {
//等待客户端连接
fmt.Println("等待客户端来链接...")
conn, err := listen.Accept()
if err != nil { //一个链接出错不需要return,其他链接可能正常
fmt.Println("Accept() error = ", err)
} else {
fmt.Println("Accept() success conn = ", conn)
fmt.Println("client ip = ", conn.RemoteAddr().String())
}
//这里准备起一个协程,为客户端服务
go process(conn)
}
}