Go主要的目标之一就是面向大规模后端服务程序,网络通信这块是服务端程序必不可少也是至关键的一部分。
网络编程有两种:
(1)TCP Socket编程:是网络编程的主流,之所以叫TCP Socket编程,是因为底层是基于TCP/IP协议的;
(2)B/S结构的http编程,使用浏览器去访问服务器时,使用的就是http协议,而http底层就是tcp socket实现的;
计算机间需要通讯,必须要有网线、网卡或者是无线网卡;
TCP/IP模型:应用层、传输层、网络层、数据链路层、物理层;
IP地址:每个internet上的主机和路由器都有一个ip地址,它包括网络号和主机号,ip地址有ipv4(32位)或ipv6(128位),可以通过Ipconfig查看。
端口:逻辑意义上 的端口,特指tcp/ip协议中的端口。共256×256-1=65535个端口;
端口分类:
- 0是保留端口;
- 1-1024是固定端口(22:ssh远程登录协议,23:telnet使用,21:ftp使用,25:smtp服务使用,80:lis使用,7:echo服务)
- 1025-65535:是动态端口,供程序员使用;
服务端和客户端之间通信框图:
可以看出,它们之间的通信是通过端口 (由于是简易的通讯,目前客户端并不能直接交流,只能通过客户端)
server.go
package main import ( "fmt" net" ) func process(conn net.Conn) { //这里接受客户端的数据 defer conn.Close() for { 创建一个新的切片 buf := make([]byte,1024) 等待客户端发送信息,如果客户端没发送,协程就阻塞在这 fmt.Printf("服务器在等待客户端%v的输入\n",conn.RemoteAddr().String()) n,err := conn.Read(buf) if err != nil { fmt.Println("服务器read err=",err) fmt.Println(客户端退出了) return } 显示客户端发送内容到服务器的终端 fmt.Print(string(buf[:n]) + \n) } } func main() { fmt.Println(服务器开始监听...) 协议、端口 listen,err := net.Listen(tcp",1)">0.0.0.0:8888 nil { fmt.Println(监听失败,err=,err) } 延时关闭 defer listen.Close() 循环等待客户端连接 fmt.Println(等待客户端连接...) conn,err := listen.Accept() nil { fmt.Println(Accept() err=else { fmt.Printf(Accept() suc con=%v,客户端Ip=%v\n这里准备起个协程为客户端服务 go process(conn) } fmt.Printf("监听成功,suv=%v\n",listen) }
client.go
bufioosstrings ) func main() { 同样是tcp协议,192.168.1.145服务端的ip地址,这里是我自己本机的地址,可在终端用ipconfig查看,后面是服务端开启的端口号 conn,err := net.Dial(192.168.1.145:8888client dial err=哭护短在命令行输入单行数据 reader := bufio.NewReader(os.Stdin) 从终端读取一行用户的输入,并发给服务器 line,err := reader.ReadString(''readString err=去掉输入后的换行符 line = strings.Trim(line,1)">\r\n如果是exit,则退出客户端 if line == exit { fmt.Println(break将line发送给服务器 _,e := conn.Write([]byte(line)) if e !=conn.write err= fmt.Printf("客户端发送了%d字节的数据,并退出",n) } }
首先在一个终端打开服务器:
然后连接两个客户端:
注意到,每个客户端的端口号是不一致的:
然后两个客户端分别发送消息给服务端:
服务端可以接收到信息:
最后输入exit分别关闭两个客户端:
两个客户端都退出了,然后服务端继续等待新的客户端的连接。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。