[TOC] # 简介 网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.socket也具有一个类似打开文件的函数调用:socket(),该函数返回有一个整形的socket描述符,随后的连接建立,数据传输等操作都是通过它实现的 常用的socket类型有两种:流式socket(`SOCK_STREAM`)和数据报式socket(`SOCK_DGRAM`) * 流式是一种面向连接的socket,针对面向连接的tcp服务应用 * 数据报式socket是一种无连接的socket,对应于无连接的udp服务应用 ![](https://box.kancloud.cn/d237f0f03353c1401e665eea53e5040f_1190x1260.png) **listen创建的socket不用于通信,用于监听地址的,accept的socket是用来通信的** ![](https://box.kancloud.cn/2076d9f847b34c6783e6c6fb538553cf_1203x440.png) read读服务/客户,有返回0,对端关闭和你连接了 # 函数 **server端** Listen函数 ~~~ func Listen(network, address string) (Listener, error) ~~~ network:tcp或者udp address:ip端口号比如127.0.0.1:9194或者:8005 Listener接口 ~~~ type Listener interface { Accept() (Conn, error) Close() error Addr() Addr } ~~~ Conn接口 ~~~ type Conn interface { Read(b []byte) (n int, err error) Write(b []byte) (n int, err error) Close() error LocalAddr() Addr RemoteAddr() Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error } ~~~ # tcp服务代码 ~~~ func main() { listener, err := net.Listen("tcp", "0.0.0.0:8183") if err != nil { fmt.Println("err = ", err) return } //退出前把监听关闭 defer listener.Close() //阻塞等待用户链接 for { conn, err := listener.Accept() if err != nil { fmt.Println("err = ", err) continue } //接收用户的请求 //1024缓冲区 buf := make([]byte, 1024) n, err1 := conn.Read(buf) if err1 != nil { fmt.Println("err1 = ", err1) continue } fmt.Println("buf = ", string(buf[:n])) //关闭当前用户的连接 defer conn.Close() } } ~~~ # tcp客户端 ~~~ func main() { conn, err := net.Dial("tcp", "127.0.0.1:8183") if err != nil { fmt.Println("err = ", err) return } defer conn.Close() //发送数据 conn.Write([]byte("are u ok?")) } ~~~ # 服务端多人 用nc做客户端,telnet做客户端好像会多传东西 ~~~ func HandleConn(conn net.Conn) { //获取客户端的网络地址信息 addr := conn.RemoteAddr().String() fmt.Println("连接成功: ", addr) //关闭连接 defer conn.Close() buf := make([]byte, 2048) for { //读取用户数据,如果客户端关闭了,好像是能发现这边的n是等于0的 n, err := conn.Read(buf) if err != nil { //客户端意外关闭,也能发现 fmt.Println("err = ", err) return } //打印数据 fmt.Println("数据是: ", string(buf[:n])) //看里面多了哪些东西 fmt.Println("长度是: ", len(string(buf[:n]))) //因为客户端传递来的有\n if "exit" == string(buf[:n-1]) { fmt.Println(addr, " exit") return } //把数据转化为大写再发送 conn.Write([]byte(strings.ToUpper(string(buf[:n])))) } } func main() { listener, err := net.Listen("tcp", "0.0.0.0:8183") if err != nil { fmt.Println("err = ", err) return } //退出前把监听关闭 defer listener.Close() //阻塞等待用户链接 for { conn, err := listener.Accept() if err != nil { fmt.Println("err = ", err) return } //处理用户请求 go HandleConn(conn) } } ~~~ # 可输入回复客户端 ~~~ func main() { conn, err := net.Dial("tcp", "127.0.0.1:8183") if err != nil { fmt.Println("net.Dial err = ", err) return } //main调用完毕,关闭连接 defer conn.Close() //接收服务器回复的数据 go func() { //从键盘输入内容,给服务器发送内容 str := make([]byte, 1024) for { n, err := os.Stdin.Read(str) if err != nil { fmt.Println("错误信息是: ", err) return } //把输入的内容发给服务器 conn.Write(str[:n]) } }() //切片缓冲 buf := make([]byte, 1024) for { //如果服务端关闭和你连接,这边的n是能读取到0的 n, err := conn.Read(buf) if err != nil { fmt.Println("错误信息是: ", err) return } fmt.Println(string(buf[:n])) } } ~~~