前两天写了tcp通信的golang示例代码,经过自己测试玩,发现存在两个问题;
1.客户端发送空字符后,服务端就收不到新的消息了,而且客户端也发送不了消息,既然客户端发送空字符串会导致问题产生,那么在客户端发送前进行是否空字符串检查,不就可以避免这个问题的发生了吗,事实证明却是如此;
2.客户端如果不是正常发送bye或者任何自定义的结束连接,而是直接ctrl+C结束连接,那么也会导致服务端自动停止监听,报 EOF conn.Read,想那如果在客户端进行读数据前对是否产生了EOF错误进行处理,那这个问题应该也是可以避免的;
这次经过测试,却是可以避免,那么如果实际要使用,就继续对收到的字符串做判断,调用合适的函数处理,那么一个tcp通信的程序应该就算是完成的差不多了吧。
package main
import (
"fmt"
"io"
"net"
"os"
)
func handerror(err error, why string) {
if err != nil {
fmt.Println(err, why)
os.Exit(1)
}
}
func withaccept(conn net.Conn) {
buffer := make([]byte, 1024)
for {
//err := conn.Close()
if conn != nil {
n, err := conn.Read(buffer)
//handerror(err, "conn.read")
if err == io.EOF {
fmt.Println("client had closed")
break
} else {
if len(buffer) > 0 {
clientmsg := string(buffer[0:n])
if clientmsg != "bye" {
fmt.Printf("recive client %s msg: %s \n", conn.RemoteAddr(), clientmsg)
conn.Write([]byte("had read:" + clientmsg))
} else {
conn.Write([]byte("bye"))
break
}
}
}
} else {
continue
}
}
fmt.Printf("The client %s has say bye\n", conn.RemoteAddr())
}
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8080")
handerror(err, "net.Listen")
for {
conn, err := listener.Accept()
handerror(err, "listener.Accept")
go withaccept(conn)
}
}
客户端代码
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func tcperror(err error, when string) {
if err != nil {
fmt.Println(err, when)
os.Exit(1)
}
}
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8080")
tcperror(err, "net.Dial")
buffer := make([]byte, 1024)
for {
reader := bufio.NewReader(os.Stdin)
linebytes, _, err := reader.ReadLine()
tcperror(err, "reader.readline")
if len(linebytes) > 0 {
n, err := conn.Write(linebytes)
tcperror(err, "conn.write")
fmt.Printf("client send %d to server\n", n)
n, err2 := conn.Read(buffer)
tcperror(err2, "conn.read")
servermsg := string(buffer[0:n])
if servermsg != "bye" {
fmt.Println("recived server msg,", servermsg)
} else {
conn.Write([]byte("i will back"))
break
}
}
}
fmt.Println("The client closed connection")
}
原文:https://www.cnblogs.com/warrior-tian/p/12845745.html