紧接着前面的章节,此篇,在tcp client端引入了锁、interfce、类的思想进去。
废话没有
tcp server端(跟上一篇一样)
<span style="font-family: Arial, Helvetica, sans-serif;">package main</span><pre name="code" class="html">
import (
"fmt"
"net"
"strings"
// "time"
)
var exit_all = make(chan string)
func recv_msg(conn net.Conn, quit chan<- int) {
defer func() {
quit <- 0
}()
for {
recv_buf := make([]byte, 1024)
lenght, err := conn.Read(recv_buf) //接受客户端数据
if err != nil {
break
}
data := string(recv_buf[:lenght])
if strings.EqualFold(data, "Quit") {
break
} else {
fmt.Printf("\rclient:%s", data) //打印客户端发送的内容
fmt.Printf("\rserver:")
}
}
}
func send_msg(conn net.Conn, quit chan<- int, exit chan<- int) {
var data string //输入发送的内容
defer func() {
quit <- 0
// time.Sleep(1 * time.Second)
exit <- 0
}()
for {
data = ""
fmt.Printf("server:")
fmt.Scanln(&data)
send_buf := []byte(data)
if strings.EqualFold(data, "Exit") {
break
}
_, err := conn.Write(send_buf) //向服务器发送数据
if err != nil {
fmt.Println(err)
continue //发送出现错误,继续
}
}
}
func close_msg(conn net.Conn, quit <-chan int, exit <-chan int) {
for {
select { //此处仅仅为了用select而用
case <-quit:
conn.Close()
fmt.Printf("\rclient is disconnected\n")
fmt.Println("wait for connection...")
case <-exit:
exit_all <- "EXIT ALL"
}
}
}
func accept_conn(listener net.Listener) {
for {
conn, err := listener.Accept() //接受客户端请求
if err != nil {
fmt.Println(err)
continue
}
fmt.Println("connect successfunlly!")
quit, exit := make(chan int), make(chan int)
go recv_msg(conn, quit)
go send_msg(conn, quit, exit)
go close_msg(conn, quit, exit)
}
}
func main() {
//监听端口
listener, err := net.Listen("tcp", "localhost:7087")
if err != nil {
fmt.Println(err)
return
}
go accept_conn(listener)
for v := range exit_all {
fmt.Println(v)
break
}
}
tcp client端(变化)
package main
import (
"fmt"
"net"
"strings"
"sync"
)
type message struct {
data string
quit chan int
mutex *sync.Mutex
}
func (msg *message) send_msg(conn net.Conn) {
for {
fmt.Printf("client:")
msg.mutex.Lock()
msg.data = "" //输入发送的内容
fmt.Scanln(&msg.data)
send_buf := []byte(msg.data)
msg.mutex.Unlock()
_, err := conn.Write(send_buf) //向服务器发送数据
if err != nil {
fmt.Println(err)
continue //发送出现错误,继续
}
}
}
func (msg *message) recv_msg(conn net.Conn) {
for !strings.EqualFold(msg.data, "Quit") { //收到Quit时退出
recv_buf := make([]byte, 1024)
lenght, err := conn.Read(recv_buf[0:]) //接受客户端数据
if err != nil {
break
}
msg.mutex.Lock() //这样加锁,其实不好的,因为for循环中还在用msg.data
msg.data = ""
msg.data = string(recv_buf[0:lenght]) //这里若不用leng,取到的data长度将会是1024
fmt.Printf("\rserver:%s", msg.data) //服务器发送的内容
msg.mutex.Unlock()
fmt.Printf("\rclient:")
}
conn.Close()
msg.quit <- 0
fmt.Println("server is disconnected")
}
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:7087") //连接服务器
if err != nil {
fmt.Println(err)
return
}
fmt.Println("If you want to exit,please input Quit")
msg := &message{data: "", quit: make(chan int), mutex: new(sync.Mutex)}
go func() { msg.send_msg(conn) }()
go func() { msg.recv_msg(conn) }()
<-msg.quit
}