道者编程


GO TCP编程

这里用到了net.Conn接口

package main
import(
	"fmt"
	"net" // 网络I/O包
	"strings" // 字符串处理包
	"time"
)

func main() {
	// 监听 88端口
	const port string = "88"
	listener , err := net.Listen("tcp","0.0.0.0:"+port)
	// 成功:err 为空,失败:err 返回失败信息
	if err != nil { 
		fmt.Println("监听失败:",listener) // 失败信息
		return // 跳出
	}
	fmt.Printf("端口为 %s 的Server准备就绪……\n",port)

	/*
	延迟释放资源
	函数返回、函数结束或者对应的goroutine发生panic的时候defer执行
	*/
	defer listener.Close() 

	// 循环等待客服端链接,阻塞
	for {
		conn , err := listener.Accept() // 接受客户端数据
		if err != nil {
            fmt.Println("连接失败")
            return //跳出
        }
        fromConn := conn
        fmt.Printf("来自 %v 的连接已建立\n", fromConn.RemoteAddr())
        defer conn.Close()
    	go connHandler(conn) // 并发、协程,如果有请求,创建goroutine负责数据收发
	}
}

//net.Conn类型,这里c要大写
func connHandler(cli net.Conn ){
	// 分配内存空间,创建一个长度为 10240 的byte数组
	buffer := make([]byte, 10240)
	// 循环接收,客户端连接后,如果不断开,可反复发送数据
	for {
		if err := cli.SetReadDeadline(time.Now().Add(time.Minute*3)); err != nil {
			return
		}

		n , err := cli.Read(buffer) // net.Conn收到的数据读到buffer,并返回数据长度 n 
		// 如果发送空数据,或者读取失败,关闭相互连接
		if n == 0 || err != nil {
	    	cli.Close()
	        return 
	    }
	    if err := cli.SetReadDeadline(time.Time{}); err != nil {
			return
			cli.Close()
        	fmt.Printf("来自 %v 的连接一直不发数据,断开\n",cli.RemoteAddr()) // 服务端打印
		}
	    // 客服端数据转string,去除两端空格
	    str := strings.TrimSpace(string(buffer[0:n]))
	    fmt.Printf("来自 %v 的连接发送了数据:%s\n",cli.RemoteAddr(),str) // 服务端打印
	    cli.Write([]byte(str)) // 回应客户端
	}
}
 


最新评论:
我要评论:

看不清楚


链接