网络编程(TCP)

分类

  1. TCP socket编程,是网编的主流,底层用的是TCP/ip协议
  2. b/s结构的http编程,使用浏览器去访问服务器时,使用的http协议,但是底层依旧是tcp socket实现。

基础知识

协议

TCP/IP是Internet最基本的协议,是由网络层的IP协议和传输层的TCP协议组成。

OSI模型约TCP/IP参考模型

层级(从高到低)OSI 模型(7 层)主要功能TCP/IP 模型(4 层)对应关系说明
7应用层(Application)提供用户接口和网络服务(如邮件、文件传输)应用层
6表示层(Presentation)数据格式转换、加密解密、压缩等应用层OSI 的应用层 + 表示层 + 会话层 合并为 TCP/IP 应用层
5会话层(Session)建立、管理和终止会话应用层
4传输层(Transport)端到端通信,提供可靠(TCP)或高效(UDP)传输传输层功能基本一致
3网络层(Network)逻辑寻址(IP)、路由选择网络层(Internet Layer)功能基本一致,使用 IP 协议
2数据链路层(Data Link)节点间帧传输、错误检测、流量控制链路层(Link Layer)TCP/IP 链路层 ≈ OSI 数据链路层 + 物理层
1物理层(Physical)传输原始比特流,定义电缆、电压、接口等物理特性链路层(Link Layer)

案例:

image-20260129181544103

IP地址

每个Internet上的主机和路由器都有一个ip地址,它包括网络号和主机号,ip地址有ipv4和ipv6,可以通过ipconfig来查看

端口

这里的端口不是物理意义上的端口,式TCP/IP协议中的端口,是逻辑意义上的端口。

只要是做服务的程序,都必须监听一个端口,该端口就是其他程序和该服务通讯的通道,所以一个端口一旦呗某个程序监听,其他程序就不能在该端口监听。

注意:

  1. 0号为保留端口
  2. 1-1024为固定端口,也叫又名端口,被某些程序固定使用,一般程序员不使用:22–SSH远程登陆协议,23–telnet使用,21–ftp使用等等
  3. 1025-65535是动态端口程序员可以使用
  4. 尽可能少开端口。
  5. netstat -an可以查看本机监听哪些端口,用netstat -anb来查看查看监听端口的pid,结合任务管理器关闭不安全的端口。

快速入门

流程

服务器端

  1. 监听端口
  2. 接收客户端的tcp链接,建立客户端和服务器端的链接
  3. 创建goroutine,处理链接的请求

客户端

  1. 建立与服务器的链接
  2. 发送请求数据,接受服务器端的返回结果数据
  3. 关闭链接

常用包

net

需求:

服务器端

  1. 写一个服务器端程序,在8888端口监听
  2. 可以和多个客户端创建链接
  3. 连接成功后,客户端可以发送数据,服务器端接收数据显示在终端上
  4. 使用telnet来测还是,然后编写客户端程序来测试

server.go

 package main
 ​
 import (
  "fmt"
  "net"
 )
 ​
 func process(conn net.Conn) {
  /*循环接收数据*/
  defer conn.Close() /*要及时关闭,要不一直不释放容易炸*/
  for {
  buf := make([]byte, 1024)
  fmt.Printf("服务器等待%s输入\n", conn.RemoteAddr().String())
  n, err := conn.Read(buf) /*等待客户端通过conn发送信息,如果客户端没有write,协程就阻塞在这里*/
  if err != nil {
  fmt.Println("服务器端Read err:", err)
  return
  }
  /*显示发送的内容*/
  fmt.Print(string(buf[:n]))
  }
 }
 func main() {
  fmt.Println("服务器开始监听")
  listen, err := net.Listen("tcp", "0.0.0.0:8888")
  /*使用tcp协议,监听8888端口*/
  if err != nil {
  fmt.Println("err:", err)
  return
  }
  defer listen.Close()
  /*循环等待客户端链接*/
  for {
  fmt.Println("等待连接ing")
  conn, err := listen.Accept()
  if err != nil {
  fmt.Println("accepy err", err)
  }
  fmt.Printf("accept =%v 客户端Ip为:%v", conn, conn.RemoteAddr())
  go process(conn)
  }
 ​
 }
 ​

客户端

  1. 链接服务器端的8888端口
  2. 客户端可以发送单行数据然后退出
  3. 能通过终端输入数据,输入一行发一行
  4. 在终端输入exit退出程序

client.go

 package main
 ​
 import (
  "bufio"
  "fmt"
  "net"
  "os"
  "strings"
 )
 ​
 func main() {
  conn, err := net.Dial("tcp", "127.0.0.1:8888")
  if err != nil {
  fmt.Println("client dial err = ", err)
  return
  }
  /*获取一行*/
  reader := bufio.NewReader(os.Stdin) /*os.Stdin表示标准输入(终端)*/
  for {
  line, err := reader.ReadString('\n')
  if err != nil {
  fmt.Println("readstring err:", err)
  }
  line = strings.Trim(line, "\n\r")
  if line == "exit" {
  fmt.Println("客户端退出")
  break
  }
  /*发送*/
  n, err := conn.Write([]byte(line + "\n"))
  if err != nil {
  fmt.Println("conn.Write err:", err)
  }
  fmt.Println(n)
  }
 ​
 }
 ​

结语

这里就只是简单讲解喵(后面在慢慢深入学习)

暂无评论

发送评论 编辑评论


				
上一篇
下一篇