HTTP 是什么:你打开 localhost:8080 时发生了什么

🥰个人主页:会编程的土豆(欢迎来访)

💎作者简介:后端学习者

❄️个人专栏:数据结构与算法数据库leetcode

那些你一个人走过的夜路,终将化作照亮未 来的光

系列:《影院票务 GO》知识点博客 · 第 1 篇(最基础)

对应项目:「影院票务 」

读完能清楚:浏览器、服务器、请求、响应、URL、端口分别是什么


写在前面

学 Web 项目,很多人一上来就扎进框架、路由、ORM,结果被学长一问:

「用户点一下购票,数据是怎么到服务器的?」

答不上来,其实答案的底层就一个词:HTTP

本篇不写框架,只把「打开 http://localhost:8080」这件事拆开讲透。

后面所有 Go 代码------ListenAndServe、Handler、JSON API、登录 Cookie------都站在这个基础上


1. 先建立一张生活中的图景

把购票网站想成一家电影院售票窗口

现实 对应到 Web
你(观众) 客户端 Client(通常是浏览器)
售票窗口 服务器 Server(我们的 Go 程序)
你说的话:「我要两张晚上 7 点的票」 请求 Request
窗口回答:「好的,订单号是 xxx」 响应 Response
你们约定用普通话沟通 协议 Protocol(这里是 HTTP)

要点:

  • 客户端主动开口,服务器一般在窗口后面等着
  • 没有请求,服务器不会无缘无故给你推一整页电影列表(至少在经典 HTTP 模型里如此)
  • 一次对话通常是:一问一答。问完答完,这次「对话回合」就结束了

你在地址栏输入 http://localhost:8080 并回车,本质上就是:

浏览器作为客户端,向本机 8080 端口上的服务器,发出了一次 HTTP 请求;

我们的 Go 程序收到后,返回一段 HTML;

浏览器把 HTML 画成你看到的页面


2. URL 拆开看:每一段都有含义

以项目地址为例:

复制代码
http://localhost:8080/movie/1
│      │         │    │
│      │         │    └─ 路径 path:要访问的资源
│      │         └────── 端口 port:服务器「窗口号」
│      └──────────────── 主机 host:哪台机器
└─────────────────────── 协议 scheme:用什么规则说话

2.1 协议 http

表示「我们按 HTTP 规则通信」

还有 https:在 HTTP 外面加了一层加密(TLS)

课程项目本地开发常用 http;上线网站几乎都是 https

拓展:

协议可以想成「快递面单格式」,大家都按同一格式写收件人、电话、物品,快递公司才认识HTTP 规定了请求行怎么写、头部有哪些字段、正文怎么跟在后面

2.2 主机 localhost

localhost 是「本机」的别名,一般解析到 127.0.0.1

所以:

  • http://localhost:8080http://127.0.0.1:8080
  • 只在你自己电脑上能访问(除非做了额外配置)

拓展:

如果以后把服务部署到云服务器,主机就会变成公网 IP 或域名,例如 https://ticket.example.com。协议和路径概念不变,变的只是「窗口开在哪栋楼」。

2.3 端口 :8080

一台电脑可以同时跑很多网络程序。端口用来区分「找哪个程序」。

常见端口:

端口 常见用途
80 HTTP 默认(URL 里常省略)
443 HTTPS 默认
3306 MySQL 默认
8080 开发时常用的 HTTP 备用端口

我们项目在 main.go 里大致是:

复制代码
http.ListenAndServe(cfg.Addr, app.Routes())
// cfg.Addr 默认是 ":8080"

含义:在 本机所有网卡的 8080 端口 上听请求。

":8080" 前面省略主机,表示绑定到本机。

被拷问时可以这样说:

「浏览器访问 8080,操作系统把连接交给正在 Listen 的 Go 进程;MySQL 在 3306,两套服务靠端口分开。」

2.4 路径 /movie/1

路径表示「你要哪个资源」。

在本项目里可以直观理解成:

路径 大致含义
/ 首页电影列表
/login 登录页
/movie/1 id 为 1 的电影详情
/api/login 登录接口(返回 JSON,不是整页 HTML)
/static/css/style.css 静态样式文件

服务器根据路径决定调用哪个处理函数------这就是后面要写的「路由」。


3. 一次 HTTP 请求长什么样?

你不必背全文,但要建立结构感。一次请求至少有三块:

3.1 请求行(第一行)

复制代码
GET /movie/1 HTTP/1.1

拆开:

  1. 方法 MethodGET(要获取资源)
  2. 路径/movie/1
  3. 协议版本HTTP/1.1

常用方法(结合本项目):

方法 直觉 项目里的例子
GET 拿数据、看页面 打开首页、打开电影详情
POST 提交数据、做动作 登录、注册、下单、支付、发评论

重要拓展:幂等直觉

  • 多次 GET /movie/1:一般只是反复看同一页,不改变服务器数据(理想情况)。
  • 一次 POST /api/order/create:会锁座位、写订单,有副作用。

所以浏览器刷新通常重发 GET;对 POST,浏览器有时会弹「是否重新提交表单」。

3.2 请求头 Headers

键值对,补充说明,例如:

复制代码
Host: localhost:8080
Accept: text/html
Cookie: ttms_sid=abc123
Content-Type: application/json

和本项目强相关的两个:

  • Cookie:带着登录会话 ID,服务器才知道你是谁。
  • Content-Type:告诉服务器正文是 JSON 还是表单。

3.3 请求体 Body

GET 通常没有 body(参数多在 URL 查询串 ?q=流浪地球)。

POST 常有 body,例如登录:

复制代码
{"username":"user","password":"user123"}

前端 fetch 发 JSON,后端用 json.Decoder 解析------后面博客会单独写。


4. 一次 HTTP 响应长什么样?

服务器回你时,也是「状态行 + 头 + 正文」。

4.1 状态码(一定要记住几类)

复制代码
HTTP/1.1 200 OK
状态码 含义 你什么时候会遇到
200 成功 页面正常打开、接口成功
302/301 重定向 未登录访问订单页,跳到 /login
404 找不到 电影 id 不存在
403 禁止 普通用户硬闯 /admin
500 服务器内部错误 数据库挂了、模板渲染崩了

讲项目时的加分说法:

「我们业务接口很多时候 HTTP 层仍返回 200,但 JSON 里用 code: 0/1 表示业务成败。这是一种常见写法:运输层成功,业务层另说。」

对应项目约定:

复制代码
{"code":0,"message":"ok","data":{...}}
{"code":1,"message":"用户名或密码错误"}

4.2 响应体可以是什么?

同是 HTTP,正文类型可以完全不同:

Content-Type 内容 项目场景
text/html 网页 //movie/1/orders
application/json 数据 /api/login/api/order/create
text/css / application/javascript 静态资源 /static/...
image/svg+xml 图片 海报 SVG

浏览器拿到 HTML 后,还会再发请求 去拉 CSS、JS、图片。

所以「打开一个首页」往往不是 1 次 HTTP,而是 很多次


5. 把整条链路串到本项目

你访问首页时,简化时间线:

复制代码
1. 你回车 http://localhost:8080/
2. 浏览器构造 GET / HTTP/1.1,发到 127.0.0.1:8080
3. Go 的 ListenAndServe 收下连接
4. ServeMux 根据路径 "/" 找到 PageHome
5. PageHome 查 MySQL 电影列表,用模板生成 HTML
6. 作为响应正文返回
7. 浏览器解析 HTML,发现还需要 /static/css/style.css 等
8. 再发若干 GET,直到页面渲染完成

如果你点「登录」:

复制代码
1. 打开 /login(GET,拿 HTML 表单页)
2. 填写账号密码,JS 发 POST /api/login(JSON body)
3. 服务器校验密码,写 Session,Set-Cookie
4. 返回 JSON {code:0, data:{role:0}}
5. 前端根据结果跳转首页或后台

同一套 HTTP,两种用法:

  • 页面请求:为人服务,返回 HTML
  • API 请求:为前端 JS 服务,返回 JSON

本项目是「服务端渲染页面 + 少量 Ajax API」的混合体,不是纯前后端分离,但对理解 HTTP 反而更完整。


6. 无状态:HTTP 为什么需要 Cookie?

经典 HTTP 被说成无状态(stateless)

服务器默认不记得「上一次是不是同一个人」。

每一请求都是新的一问一答。

那登录怎么办?总不能每次点「我的订单」都重新输入密码。

做法:服务器给你发一张「手环」------Cookie

下次请求浏览器自动带上,服务器一看 Session ID,就知道你是 user

这会在后续博客「Cookie 与 Session」展开。现在只要记住:

HTTP 本身不记人;登录态是我们在 HTTP 之上「加」出来的。


7. 和 TCP 的关系(拓展,够答辩用)

常有人问:「HTTP 和 TCP 啥关系?」

可以答三层蛋糕(极度简化):

复制代码
应用层   HTTP   ------ 说什么内容(要哪页、JSON 是什么)
传输层   TCP    ------ 怎么可靠送达(分包、重传、顺序)
网络层   IP     ------ 去哪台机器

浏览器发 HTTP 之前,通常先和服务器做 TCP 三次握手 建连,然后在连接上写 HTTP 报文。

你写 Go 业务时几乎摸不到 TCP,但要知道:

  • 端口是传输层的概念
  • ListenAndServe 底下就是在听 TCP,再解析 HTTP

不必在课程答辩里把三次握手背到发抖,但能说出「HTTP 跑在 TCP 上」就够用。


8. 用开发者工具亲眼看一次(强烈建议做)

  1. 启动本项目,打开 Chrome / Edge
  2. 访问 http://localhost:8080
  3. F12 → Network(网络)
  4. 刷新页面

你会看到:

  • 第一条往往是文档 localhost,类型 Document,状态 200
  • 后面一串 .css / .js / .svg
  • 点开某一条,看 Headers:Request URL、Method、Status Code、Request Headers、Response Headers
  • Response:HTML 或 JSON 原文

再登录一次,观察:

  • POST /api/login
  • 响应里是否有 Set-Cookie
  • 之后请求是否自动带上 Cookie: ttms_sid=...

这比背概念牢固十倍。学长若问「你怎么验证登录态的」,你可以回答:「抓包看 Cookie」。


9. 和本项目代码的对应关系(预习下一篇)

HTTP 概念 项目里落在哪
监听端口 http.ListenAndServe(cfg.Addr, ...)
路由 handlers/routes.goHandleFunc
返回 HTML a.Render(... template ...)
返回 JSON utils.OK / utils.Fail
静态资源 /static/http.FileServer
登录态 Cookie + store/session.go

下一篇我们会从 main.go 讲:Go 程序如何开始跑,为何先连数据库再 Listen


10. 常见误区

  1. 「HTTP 就是网站」

    不准确。HTTP 是通信约定;网站是用 HTTP(等)堆出来的应用。

  2. 「JSON 不是 HTTP」

    JSON 只是响应/请求正文的一种格式;车是 HTTP,货可以是 JSON 或 HTML。

  3. 「localhost 只能自己访问,所以上线也写 localhost」

    上线要换成域名或服务器地址;localhost 永远指「访问者自己的电脑」。

  4. 「端口随便写」

    可以换,但浏览器访问必须和 Listen 的端口一致;且不要和 MySQL 的 3306 搞混。


11. 小结(可直接当口述稿)

HTTP 是浏览器和服务器之间约定好的问答协议。

URL 里有协议、主机、端口、路径。

请求有方法、头、可选正文;响应有状态码和正文。

打开我们的票务首页,就是一次(其实是一串)HTTP GET;登录下单则是 POST API。

HTTP 本身无状态,所以要用 Cookie/Session 记住登录用户。


12. 思考题

  1. 为什么访问 http://localhost:8080 可以,访问 http://localhost:3306 用浏览器通常会很奇怪甚至失败?
  2. 如果 Go 程序没启动,浏览器会报什么?这和「路径写错 404」有什么区别?
  3. 同一路径 /api/orders,未登录和已登录,服务器可能如何不同处理?这还是「无状态」吗?
  4. 打开电影详情页时,评论区如果用 JS 再请求 /api/comments,整页加载涉及几次 HTTP?试着在 Network 面板数一数。

13. 下一篇预告

《02 · Go 程序从哪里开始跑:package main 与 func main》

会逐行拆 main.go:配置、连库、定时清理、ListenAndServe 为什么阻塞,以及 log.Fatal 和普通返回错误的区别

相关推荐
M1582276905510 小时前
跨协议互通利器|SG-PN-EIP (S)-220 Profinet 转 EtherNet/IP 网关,打通欧美 PLC 通讯壁垒
网络·网络协议·tcp/ip
北龙云海10 小时前
案例分享 | 面向公网业务系统境内访问白名单配置实操方案
运维·网络·安全·网络安全·告警·数据泄露·入侵攻击
闲猫11 小时前
Spring AI对接Deepseek 使用Charles代理api.deepseek.com 拦截报文,查看Tool和Skill的本质
网络·网络协议·http
niaiheni13 小时前
Fastjson 1.2.83 “Gadget-Free“ RCE
网络·安全·web安全
意疏13 小时前
远程办公软件哪个安全性高?UU远程8项安全防线全覆盖
网络·安全
牛马之星14 小时前
气体涡轮流量计如何维护
网络·经验分享
MonolithIoT14 小时前
实战方案|设备备件无人值守仓库:连续化产线运维备件 7×24 小时数字化管控方案
运维·网络·数据库
三84415 小时前
BGP/GRE练习
网络
念恒1230616 小时前
网络基础
linux·网络·c++