协议:
一组规则。用来协定数据传输的先后规范和顺序。
网络分层模型:
OSI 7层模型:—— 理论
物、数、网、传、会、表、应
TCP/IP 4层模式:—— 实际
链、网、传、应
分层的原因,降低 各层之间的 耦合度。独立处理。
网络通信过程:
数据必须要进行网络协议层的封装,才能进入网络环境中进行传输。
数据 ——> 应用层( NFS、telnet、ftp、http。。。)——> 传输层(TCP、UDP)——> 网络层(IP) ——> 链路层(RARP/ARP)
4层作用:
链路层:
源mac地址 —— 目的mac地址。
借助 IP地址获取 mac 地址。 —— ARP协议。 RARP协议: 借助 mac地址 —— IP地址。
网络层:
源IP地址 —— 目的IP
封装Ip地址。 借助IP地址,在网络环境中唯一标识 一台主机(终端)
传输层:
源port —— 目的port(端口号)—— 2字节
封装port。 端口号,在一台主机上找寻唯一个进程。
【IP+port ——> 在网络环境中,唯一标识一个进程。】
应用层:(可选)
应用 —— 应用
总结网络通信需求:
mac地址: 网卡编号。 IP ——> mac 地址。(不需要用户指定,系统自动完成)
IP地址:网络主机IP。唯一在网络环境中标识 一个终端。(需要用户指定) —— 4字节(IPv4)——“192.168.13.63”—— 点分十进制 string
port:进程的编号。在网络主机中唯一标识一个进程。(需要用户指定)
不同网络主机的 port 可以相同。
同一台主机的额 port 不能重复。
取值范围:0-65535 (2^16) 建议应用程序中,使用5000+, 8080
socket:
在一次网络通信过程中,socket必须是成对出现。
双向全双工通信。—— 同一个 socket 既可以读又可以写。
系统内核封装 socket 的基本原理: 一个socket中包含 2 个 channel , 一个channel·、另一个负责读。
IP+port == socket ——> 在网络环境中,唯一标识一个进程。
网络应用设计模型:
C/S: client -- server
优点: 1. 协议选择灵活。
2. 提前缓冲数据。
缺点: 1. 用户主机内存消耗大。
2. 授平台限制。
3. 开发工作量大。
4. 威胁用户安全。
使用场景:需要缓冲大量数据,用户对数据访问速度要求较高场合。
B/S: Browser —— server
优点: 1. 用户主机内存消耗小。
2. 不授平台限制。
3. 开发工作量小。
4. 不会威胁用户安全。
缺点:
1. 协议选择不灵活。
2. 无法缓冲大量数据。
使用场景:不需要大量数据缓存,希望跨平台处理。
TCP-CS服务器实现:
1. 创建监听 socket net.Listen("网络协议", "IP+port") ——> listener(监听)—— 不阻塞
IP: 192.168.13.63”—— 点分十进制 string
2. 阻塞监听客户端连接请求 listener.Accept() ——> conn (通信) —— 阻塞
3. 读取客户端发送数据, conn.read(buf)
4. 处理读到的数据。—— 具体业务
5. 回发数据给客户端。 conn.write()
6. 关闭 套接字(listener、conn)
添加 netcat 工具:充当客户端,测试服务器代码。
1. 解压 netcat-win32-1.12.zip 文件 到指定目录
2. 拷贝 解压后目录,保存到环境变量:
方法:我的电脑-->属性-->高级系统设置-->环境变量-->系统变量中找“path”-->双击它-->新建-->粘贴
win7 系统: 在已有的 “path”所对应的值结尾处添加一个“;”粘贴 即可。
3. 启动 cmd 执行 nc 命令 充当客户端测试
4. nc 127.0.01 8000 (注意 IP 和 端口之间是“空格”)—— 服务器的 IP、port
5. 输入 hello socket。 服务器应该能读到并向服务器的屏幕打印 “hello socket”
TCP-CS-client实现:
1. 创建用于数据通信的套接字 net.Dial("传输协议",“地址”) ——> 返回 通信套接字。 conn
地址: IP + port。(服务器的 地址)
2. 发送 数据给 服务器
conn.write()
3. 接收 服务器 数据
conn.read()
4. 关闭用于通信的套接字
conn.close()
TCP-CS-并发服务器实现:
1. 创建监听 socket net.Listen("网络协议", "IP+port") ——> listener(监听)—— 不阻塞
IP: 192.168.13.63”—— 点分十进制 string
2. 循环 阻塞等待客户端连接, 创建 子go程, 与客户端 进行数据通信
for {
conn = listener.Accept()
go handlerConnet()
}
3. 实现 handlerConnet(conn) 子go程主函数。
defer conn.Close()
for {
1)读取客户端的数据
conn.read(buf)
2) 小——大
upperStr := strings.toUpper()
3) 写回给客户端
conn.write(upperStr)
}
windows: \r:回车 \n:换行 —— cmd终端
Linux: 回车换行 \n —— nc
TCP-CS-并发客户端实现: —— 模拟实现 nc 工具
并发:读键盘的go程 与 跟服务器通信的go程 之间的并发。
1. 创建用于数据通信的套接字 net.Dial("传输协议",“地址”) ——> 返回 通信套接字。 conn
地址: IP + port。(服务器的 地址)
2. 创建 匿名 子go程, 读用户键盘输入。 将读到的内容,写给 服务器
for {
n = os.Stdin.Read(buf) // 可以读取带有空格的字符串
conn.Write(buf[:n])
}
3. 主 go程, 接收服务器回发数据。打印
for {
conn.Read(buf)
}