Golang的主要设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端程序必不可少也是至关重要的一部分
网络编程有两种
1)TCP socket编程,是网络编程的主流。之所以交TCP socket编程,是因为底层是基于Tcp/ip协议的,比如QQ聊天
2)b/s结构的http编程。我们使用浏览器去访问服务器时,使用的就是http协议,而http底层依旧是tcp socke实现的,比如京东商城(这属于go web开发范畴)
TCP/IP(Transmission Control Protocal)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通信协议,这个协议是Internet最基本的协议 internet国际互联网的基础,简单的说,就是由网络层的IP协议和传输层的TCP协议组成的
协议的抽象理解图
详细结构(模拟qq好友发送数据经过的网络协议层)
概述:每个internet上的主机和路由器都有一个ip地址,他包括网络和主机号,ip地址有ipv4(32位)和ipv6(128位),可以通过ipconfig来查看
我们这里所指的端口不是指物理意义上的端口,而是特指TCP/IP协议上的端口,是逻辑意义上的端口
如果把ip地址比作一个房子,端口就是出入这间房子的门。真正的房子只有几个门,但是一个ip地址的端口可以有65536(256256)个之多!端口是通过端口号来标记的,端口号只有整数,范围是0到65535(256256-1)
端口–分类
端口(port)-使用注意
下图为Golang socket编程中客户端和服务器的网络分布
项目示意图
1)服务端的处理流程
-1.监听端口
-2.创建客户端的tcp连接,建立客户端和服务端的连接
-3.创建goroutine,处理该连接的请求(通常客户端会通过连接来发送请求包)
server.go
package main
import (
"fmt"
"net" //做网络socket开发时。net包含有我们需要所有的方法和函数
// "io"
)
func process(conn net.Conn) {
//这里我们循环的接收客户端发送的数据
defer conn.Close() //关闭conn
for {
//创建一个新的切片
buf := make([]byte,1024)
//1.等待客户端通过conn发送信息
//2.如果客户端没有write[发送],那么协程就阻塞在这里
fmt.Printf("服务器在等待客户端%s 发送信息"+ conn.RemoteAddr().String())
n,err :=conn.Read(buf) //从conn读取
if err != nil {
fmt.Printf("客户端退出 err=%v\n",err)
return // !!!
}
//3.显示客户端发送的内容到服务器的终端
fmt.Println(string(buf[:n]))
}
}
func main() {
fmt.Println("服务器开始监听")
//net.Listen("tcp","0.0.0.0:8888")
//1.tcp表示使用网络协议是tcp
//2.0.0.0.0:8888 表示在本地监听8888端口
listen, err :=net.Listen("tcp","0.0.0.0:8888")
if err != nil {
fmt.Println("listen err")
return
}
defer listen.Close() //延时关闭listen
//循环等待客户端连接我
for {
//等待客户端连接诶
fmt.Println("等待客户端连接...")
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept() err=",err)
}else {
fmt.Println("Accept() suc conn=%v 客户端ip为=%v\n",conn,conn.RemoteAddr().String())
}
//这里准备启动一个协程为客户端服务
go process(conn)
}
// fmt.Printf("Listen successfully=%v\n",listen)
}
2)客户端的处理流程
-1.建立与服务端的链接
-2.发送请求数据,接收服务器端返回的结果数据
-3.关闭连接
3)客户端功能
-1.编写一个客户端程序,能连接到服务端的8888端口
-2.客户端可以发送单行数据,然后就退出
-3.能通过终端输入数据(输入一行发送一行),并发送给服务器端
-4.在终端输入exit表示退出程序
client.go
package main
import (
"fmt"
"net"
"bufio"
"os"
"strings"
)
func main() {
conn, err :=net.Dial("tcp","192.168.31.102:8888")
if err != nil {
fmt.Println("client dial err=",err)
return
}
//功能1.客户端可以发送单行数据,然后就退出
reader:= bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入【终端】
for {
//从终端读取一行用户输入,并准备发送给服务器
line, err :=reader.ReadString('\n')
if err != nil {
fmt.Println("readerString err=",err)
}
//如果用户输入的是exit就退出
line = strings.Trim(line, "\r\n")
if line == "exit"{
fmt.Println("客户端退出..")
break
}
//再将line发送给服务器
_, err =conn.Write([]byte(line+ "\n"))
if err != nil {
fmt.Println("conn.Write err=",err)
}
//fmt.Printf("客户端发送了%d字节的数据,并退出",n)
}
}
运行效果图
需求分析 -->设计阶段–>编码实现–>测试阶段—>实施
-1 用户注册
-2 用户登录
-3 显示在线用户列表
-4 群聊(广播)
-5 点对点聊天(私聊)
-6 离线留言
项目开发前技术准备
项目要保存用户信息和消息数据,因此我们需要学习数据库(Redis和mysql),这里我们选择redis,先学习如何在golang中使用redis