go里面实现tcp没有像之前写的C++那些那么麻烦,在C++里面要先创建套接字,然后绑定ip地址。go里面直接就一个函数建立套接字,然后在进行通信就可以了。
server
- 首先调用
Listen
函数,指定协议类型,IP地址和端口号,返回一个Listener。 Accept
函数等待客户端的连接,一样有阻塞作用。返回一个Conn。- 用Conn就可以进行通信了,go一个线程,在里面先进行数据接收,在发送。
package main
import (
"fmt"
"net"
"time"
)
func main() {
fmt.Println("hello world")
lner, err := net.Listen("tcp", "localhost:8888")
if err != nil {
fmt.Println("listener creat error", err)
}
fmt.Println("waiting for client")
for {
conn, err := lner.Accept()
if err != nil {
fmt.Println("accept error", err)
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
fmt.Println("connection success")
fmt.Println("client address: ", conn.RemoteAddr())
buffer := make([]byte, 1024)
recvLen, err := conn.Read(buffer)
if err != nil {
fmt.Println("Read error", err)
}
strBuffer := string(buffer[:recvLen])
fmt.Println("Message: ", strBuffer)
fmt.Println("Message len :", recvLen)
time.Sleep(time.Second * 1)//等一秒钟,可以看出client里面的read函数有阻塞效果
sendLen, err := conn.Write([]byte("I am server, you message :" + strBuffer))//将client发过来的消息原样发送回去
if err != nil {
fmt.Println("send message error", err)
}
fmt.Println("send message success")
fmt.Println("send message len;", sendLen)
}
client
- 之前写的C++里面,是先建立套接字,然后在
connect
。go里面直接使用Dial
,指定协议类型,地址就能连接上。然后地址的话得先用ResolveTCPAddr
进行转换一下。 - 接收的时候使用了一个线程,我看网上都说建议读写都要一个线程,我这只是一个简单的实现,只写了接收的部分。到实际应用的时候看应该怎么个做法。
package main
import (
"fmt"
"net"
"time"
)
func main() {
fmt.Println("client launch")
serverAddr := "localhost:8888"
tcpAddr, err := net.ResolveTCPAddr("tcp", serverAddr)
if err != nil {
fmt.Println("Resolve TCPAddr error", err)
}
conn, err := net.DialTCP("tcp4", nil, tcpAddr)
defer conn.Close()
if err != nil {
fmt.Println("connect server error", err)
}
conn.Write([]byte("hello , I am client"))
go recv(conn)
time.Sleep(2 * time.Second)//等两秒钟,不然还没接收数据,程序就结束了。
}
func recv(conn net.Conn) {
buffer := make([]byte, 1024)
n, err := conn.Read(buffer)
if err == nil {
fmt.Println("read message from server:" + string(buffer[:n]))
fmt.Println("Message len:", n)
}
}