(四十六)golang--网络编程(简易的聊天系统)
时间:2022-07-23
本文章向大家介绍(四十六)golang--网络编程(简易的聊天系统),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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", "0.0.0.0:8888")
if err != nil {
fmt.Println("监听失败,err=", err)
return
}
//延时关闭
defer listen.Close()
for {
//循环等待客户端连接
fmt.Println("等待客户端连接...")
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept() err=", err)
} else {
fmt.Printf("Accept() suc con=%v,客户端Ip=%vn", conn, conn.RemoteAddr().String())
}
//这里准备起个协程为客户端服务
go process(conn)
}
//fmt.Printf("监听成功,suv=%vn", listen)
}
client.go
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
//同样是tcp协议,192.168.1.145服务端的ip地址,这里是我自己本机的地址,可在终端用ipconfig查看,后面是服务端开启的端口号
conn, err := net.Dial("tcp", "192.168.1.145:8888")
if err != nil {
fmt.Println("client dial err=", err)
return
}
//哭护短在命令行输入单行数据
reader := bufio.NewReader(os.Stdin)
for {
//从终端读取一行用户的输入,并发给服务器
line, err := reader.ReadString('n')
if err != nil {
fmt.Println("readString err=", err)
}
//去掉输入后的换行符
line = strings.Trim(line, "rn")
//如果是exit,则退出客户端
if line == "exit" {
fmt.Println("客户端退出了")
break
}
//将line发送给服务器
_, e := conn.Write([]byte(line))
if e != nil {
fmt.Println("conn.write err=", e)
}
// fmt.Printf("客户端发送了%d字节的数据,并退出", n)
}
}
首先在一个终端打开服务器:
然后连接两个客户端:
注意到,每个客户端的端口号是不一致的:
然后两个客户端分别发送消息给服务端:
服务端可以接收到信息:
最后输入exit分别关闭两个客户端:
两个客户端都退出了,然后服务端继续等待新的客户端的连接。
- ASP.NET Web API 支持 CORS
- oracle odp.net 32位/64位版本的问题
- Redis+TwemProxy(nutcracker)集群方案部署记录
- 金融科技新常态,未来开启拼“硬实力”阶段
- Mono 3 的默认Gc是Sgen
- Linux下Redis主从复制以及SSDB主主复制环境部署记录
- 单元测试同时支持 NUnit/MSTest
- log4net快速上手
- MySQL高可用方案-PXC环境部署记录
- Redis主从复制下的工作原理梳理
- Linux系统下常用的数据备份方法
- K2 的Workspace 遭遇400 RequestLength 错误修复
- 从零开始学人工智能-Python·决策树(三)·节点
- .net程序员使用Oracle新手上路指南
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Logrotate实现Catalina.out日志每俩小时切割示例
- Linux常见问题解决方案汇总
- Linux中文件/文件夹无法删除的解决方案
- GNU Parallel的具体使用
- crontab定时任务不执行的原因分析与解决方法
- 在Linux中安装ASPNET.Core3.0运行时的示例代码
- linux Bash脚本判别使用者的身份方法示例
- 配置Linux使用LDAP用户认证的方法
- linux Dig命令使用大全
- Ubuntu虚拟机下使用cutecom进行串口通信的方法
- 虚拟机Linux系统忘记密码修改root或其他用户密码的方法
- 在 RHEL8 /CentOS8 上建立多节点 Elastic stack 集群的方法
- linux 搭建svn服务器的方法步骤
- linux 下隐藏进程的一种方法及遇到的坑
- Ubuntu 18.04中截图工具shutter的编辑按钮不可用的解决办法