go网络编程
敬告:本文不讲解代码,只是把代码展示出来。
1、简单示例
1.1、服务端代码
package main
import (
"fmt"
"net"
)
func process(conn net.Conn) {
// 处理客户端请求
defer conn.Close() //关闭连接,如果不关闭会因为连接数不释放,导致服务器无法接收新的连接
for {
//创建新的切片
buf := make([]byte, 1024)
//读取客户端数据。如果客户端不 conn.Write(),conn.Read()会一直阻塞
fmt.Printf("等待客户端发送数据...%v", conn.RemoteAddr())
n, err := conn.Read(buf)
if err != nil {
fmt.Println("客户端连接断开:", err)
break
}
//打印客户端发送的数据
fmt.Print("客户端发送的数据:", string(buf[:n])) //[:n]一定要写,否则会打印多余的东西出来
}
}
func main() {
fmt.Println("服务器开始监听...")
//net.Listen("tcp", "0.0.0.0:8888")
//1.tcp 表示使用网络协议是 tcp
//2. 0.0.0.0 表示监听 8888 端口
listener, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("服务器监听失败:", err)
return
}
defer listener.Close()
for {
// 等待客户端连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("服务器接收客户端连接失败:", err)
continue
} else {
fmt.Println("服务器接收客户端连接成功:", conn.RemoteAddr())
}
// 处理客户端请求
//go handleClient(conn)
go process(conn)
}
}
1.2、客户端代码
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", ":8888")
if err != nil {
fmt.Println("Error connecting to server:", err)
return
}
//客户端可以发送单行数据到服务器,然后就退出
reader := bufio.NewReader(os.Stdin) //os.Stdin是标准输入
//从终端读取一行用户输入并准备发送给服务器
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading input:", err)
}
//再讲line发送给服务器
n, err := conn.Write([]byte(line))
if err != nil {
fmt.Println("conn.Write err=", err)
}
fmt.Printf("客户端发送了%d字节的数据,并退出", n)
}
1.3、运行结果查看
服务端运行
go run ../server/net1.go
服务器开始监听...
再打开一个窗口运行客户端程序
go run client/net1.go
输入 hello test
hello test
客户端发送了11字节的数据,并退出
这时查看服务端程序的输出
服务端程序输出
服务器开始监听...
服务器接收客户端连接成功: 127.0.0.1:54263
等待客户端发送数据...127.0.0.1:54263客户端发送的数据:hello test
等待客户端发送数据...127.0.0.1:54263客户端连接断开: EOF
2、简单示例改进版代码
2.1、服务端改进代码
上述代码有个瑕疵就是每次客户端退出就会输出 EOF ,为了避免这个输出,可以使用如下代码处理
if err == io.EOF {
fmt.Println("客户端连接断开")
break
}
完整的改进版 server 端代码如下,客户端代码不变
package main
import (
"fmt"
"io"
"net"
)
func process(conn net.Conn) {
// 处理客户端请求
defer conn.Close() //关闭连接,如果不关闭会因为连接数不释放,导致服务器无法接收新的连接
for {
//创建新的切片
buf := make([]byte, 1024)
//读取客户端数据。如果客户端不 conn.Write(),conn.Read()会一直阻塞
fmt.Printf("等待客户端发送数据...%v", conn.RemoteAddr())
n, err := conn.Read(buf)
if err == io.EOF {
fmt.Println("客户端连接断开")
break
}
//打印客户端发送的数据
fmt.Print("客户端发送的数据:", string(buf[:n])) //[:n]一定要写,否则会打印多余的东西出来
}
}
func main() {
fmt.Println("服务器开始监听...")
//net.Listen("tcp", "0.0.0.0:8888")
//1.tcp 表示使用网络协议是 tcp
//2. 0.0.0.0 表示监听 8888 端口
listener, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("服务器监听失败:", err)
return
}
defer listener.Close()
for {
// 等待客户端连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("服务器接收客户端连接失败:", err)
continue
} else {
fmt.Println("服务器接收客户端连接成功:", conn.RemoteAddr())
}
// 处理客户端请求
//go handleClient(conn)
go process(conn)
}
}
2.2、运行结果查看
服务端运行
go run ../server/net1.go
服务器开始监听...
再打开
go run client/net1.go
hello test
客户端发送了11字节的数据,并退出
服务端输出
go run ../server/net1.go
服务器开始监听...
服务器接收客户端连接成功: 127.0.0.1:63275
等待客户端发送数据...127.0.0.1:63275客户端发送的数据:hello test
等待客户端发送数据...127.0.0.1:63275客户端连接断开
3、只有当客户端输入 exit 的时候,客户端程序退出
3.1、服务端代码
package main
import (
"fmt"
"io"
"net"
"os"
)
func process(conn net.Conn) {
// 处理客户端请求
defer conn.Close() //关闭连接,如果不关闭会因为连接数不释放,导致服务器无法接收新的连接
for {
//创建新的切片
buf := make([]byte, 1024)
//读取客户端数据。如果客户端不 conn.Write(),conn.Read()会一直阻塞
fmt.Printf("等待客户端发送数据...%v", conn.RemoteAddr())
n, err := conn.Read(buf)
if err == io.EOF {
fmt.Println("客户端连接断开")
break
}
if string(buf[:n]) == "exit\n" {
fmt.Println("客户端请求退出")
os.Exit(0)
}
//打印客户端发送的数据
fmt.Print("客户端发送的数据:", string(buf[:n])) //[:n]一定要写,否则会打印多余的东西出来
}
}
func main() {
fmt.Println("服务器开始监听...")
//net.Listen("tcp", "0.0.0.0:8888")
//1.tcp 表示使用网络协议是 tcp
//2. 0.0.0.0 表示监听 8888 端口
listener, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("服务器监听失败:", err)
return
}
defer listener.Close()
for {
// 等待客户端连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("服务器接收客户端连接失败:", err)
continue
} else {
fmt.Println("服务器接收客户端连接成功:", conn.RemoteAddr())
}
// 处理客户端请求
//go handleClient(conn)
go process(conn)
}
}
3.2、客户端代码
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
conn, err := net.Dial("tcp", ":8888")
if err != nil {
fmt.Println("Error connecting to server:", err)
return
}
//客户端可以发送单行数据到服务器,然后就退出
reader := bufio.NewReader(os.Stdin) //os.Stdin是标准输入
for {
//从终端读取一行用户输入并准备发送给服务器
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading input:", err)
}
//如果用户输入的是exit,则退出程序
line = strings.Trim(line, " \r\n")
if line == "exit" {
fmt.Println("Exiting...")
conn.Close()
break
}
//再将line发送给服务器
_, err = conn.Write([]byte(line + "\n"))
if err != nil {
fmt.Println("conn.Write err=", err)
}
}
}
3.3、运行结果查看
服务端运行
go run ../server/net1.go
服务器开始监听...
再打开一个终端,运行客户端代码
go run net1.go
hello
我这里可以测试连续 输入输出
我将要退出
exit
Exiting...
服务端输出
go run ../server/net1.go
服务器开始监听...
服务器接收客户端连接成功: 127.0.0.1:53864
等待客户端发送数据...127.0.0.1:53864客户端发送的数据:hello
等待客户端发送数据...127.0.0.1:53864客户端发送的数据:我这里可以测试连输入输出
等待客户端发送数据...127.0.0.1:53864客户端发送的数据:我将要退出
等待客户端发送数据...127.0.0.1:53864客户端连接断开