server端的实现:
package main
import (
"fmt"
"net" //做网络socket开发时,net包含有我们需要所有的方法和函数
)
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() //延时关闭listen
for {
fmt.Println("等待客户端来连接。。。")
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept err=", err)
} else {
fmt.Printf("Accept() con=%v,ip=%v\n", conn, conn.RemoteAddr().String())
}
}
}
clent端的实现:
//利用dial函数和服务器建立连接的格式
//conn , err := net.Dial("tcp","google.com:80")
package main
import (
"fmt"
"net"
)
func main() {
conn, err := net.Dial("tcp", "0.0.0.0:8888")
if err != nil {
fmt.Println("clent dial err=", err)
return
}
fmt.Println("conn 成功=", conn)
}
使用conn.RemoteAddr().String(),可以将ip地址显示出来,这个ip地址是和server端建立连接的ip地址。
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept err=", err)
} else {
fmt.Printf("Accept() con=%v,ip=%v\n", conn, conn.RemoteAddr().String())
}
进行两次连接,发现虽然客户端的地址都是一样的但是端口是不一样的,因为在连接的过程中,客户端的端口是随机分配的,并不是固定的。
服务器端定义一个处理函数,可以进行读取从客户端发送的信息。
func process(conn net.Conn) {
//在这里,可以循环的接受客户端发送的数据
defer conn.Close() //关闭这个conn
for {
//每次都要创建一个新的切片
buf := make([]byte, 1024)
//conn.Read(buf)
//1.等待客户端通过conn发送信息
//2.如果客户端没有writer[发送],那么这个协程就阻塞在这里
fmt.Printf("服务器在等待客户端发送信息%s\n", conn.RemoteAddr().String())
n, err := conn.Read(buf) //从conn读取
if err != nil {
fmt.Println("服务器端的Read err=", err)
return
}
//3.显示客户端发送的内容到服务器的终端
fmt.Print(string(buf[:n])) //n 代表的是从管道中真正读到的内容是什么
}
}
客户端的功能:
开一个reader,读入的是标准输入,os.Stdin,conn.Writer是将读入的东西写入到conn中,这样从server中就可以获取到读入的信息。
//功能1,客户端可以发送单行数据,然后就退出
reader :=bufio.NewReader(os.Stdin)//os.Stdin,是标准输入
//从终端读取一行用户输入,并准备发送给服务器
line , err := reader.ReadString('\n')
if err!= nil{
fmt.Println("readString err=",err)
}
//再将line 发送给服务器
n , err := conn.Write([]byte(line))
if err!= nil{
fmt.Println("conn.Writer err=",err)
}
fmt.Printf("客户端发送了%d字节的数据,并退出",n)
效果图如图: