学习golang(1) 初探:写一个简单的TCP服务器

简介: 学习golang(1) 初探:写一个简单的TCP服务器

网络通信的方式有哪些


我们对于网络通信方式而言,大概可以分为以下三类方式


  • 客户端/服务器结构
  • P2P结构
  • 混合结构




客户端/服务器结构


客户端/服务器通信方式通常称为C/S(client/server)通信方式,它作为网络中最典型、最基本的通信结构。


在通信过程中,服务器先启动服务,分配套接字,由客户端连接服务器,进行通信,在此过程中,客户端为主动方,服务器为被动方。客户端和客户端不允许直接通信。


这里提一点,很多文章说的B/S通信,本质上也是C/S通信哈。



P2P结构

在P2P通信中,通信双方都是对等关系,也就是说,P2P结构中,通信双方既可以作为服务器,又可以作为客户端。


混合结构

顾名思义,混合结构就是既有服务器存在,又有对等网存在,不过一般是先和服务器建立连接后,进行获取其他客户端套接字,然后进行通信。


总结

我们虽然区分了三种网络通信方式,但是从另一点来看,如果想要提供服务器,那么就需要提前开启服务并且分配一个套接字,等待别的客户端通过这个套接字连接上来,所以说C/S结构才是最基本的通信方式。



编写一个简单的TCP服务器/客户端


服务器

image.png

image.png


如上所述,我们使用net.Listen("tcp", "0.0.0.0:8881")来监听所有网卡的8881端口,这就是套接字

我们使用 listen.Accept()该函数会等待一直到客户端连上服务器,若连接后,我们就得到了一条连接

conn.Read(buf)表示从连接中读取数据,并且写入我们新建的byte数组中

使用 conn.Write(append([]byte("hello juejin pdudo "), buf...))将数据写入该连接

最后使用 conn.Close()来关闭该连接。

写完我们可以运行起来,然后使用telnet 来简单测试一下

使用telnet 127.0.0.1 8881可以连接进我们新写好的服务器,我们输入字符hello juejin,服务器返回了我们hello juejin pdudo hello juejin

image.png

我们查看服务器日志

image.png



客户端

我们再写个客户端在看看

image.png


测试

我们先启动服务器

启动服务器后并启动客户度

image.png


客户端日志

image.png

由此,我们一个简单的服务器和客户端便写好了




什么是粘包


模拟粘包

我们常说,tcp是流,建立握手连接后,该TCP连接就像水一样,源源不断的通信,我们没办法区分哪儿是数据的头,哪儿是数据的尾,所以才会出现粘包的东西

那我们可以尝试一下粘包

我们修改一下客户端

image.png


我们只发送,不接受,看看服务器收到的日志

先启动服务器,然后启动客户端,我们得到的日志是这样的?

image.png

揉成一团来发了。本来我们发送的条数是5条,但是服务器接受到的就这一条,这就是粘包。



如何避免粘包


如上所述,我们出现粘包的原因是: 没有办法确定需要发送/需要接受数据的长度,那如果我们能够确认发送/接受的数据,不就可以避免粘包了么。


那我们可以在发送的数据前面,加一个数据,这个数据就是字符的长度,例如,

我们想发送一个字符串: "hello juejin pdudo",按照我们之前设想的,模拟出来应该是这样的


image.png

我们如何写入18这个数据呢? 这就引入了我们下面介绍的,什么是大端序和小端序




什么是大端序/小端序


早些时候,计算机 比 网络要出现的早,各自搞各自的,其中和字节顺序有关的是,如何存储这类垮字节的数据,出现了2个极端,一个认为最低有效字节在前,一种认为最高有效字节在前,所以出现了 大端序 和 小端序

我们将低字节放在前面的方法,我们称之为 小端法

反之,我们将高字节放在前面的方法,称之为 大端法


后面网络出现了,使得这2种计算机通信起来有问题,未必避免这种情况,那么就会规定一下该操作使用什么大端序或者小端序,例如我们之前看的dns协议,就是使用的大端序,所以我们需要拿到数据包后,解一下字节序。


具体什么意思呢?

我们来看下,假设我申请了一个 无符号32位整形数据 ,我们为其赋值为 8

那么它的字节图应该是这样的

image.png

我们按照大端和小端来看一下

小端序

image.png

大端序

image.png


为什么我们上面定义的简单服务器中发送字符为什么没有使用大端或者小端呢?

如前面所讲,大端序和小端序对应的是多个字节,而我们使用的字符是一个字节,不管怎么排,都没有问题。



解决粘包问题


我们了解了如何避免粘包,以及字节排列顺序,所以,我们实现一下如何避免粘包

我们规定有4个字节来存储字符的长度嘛

我们在golang中使用encoding/binary来实现相应的字节序

我们使用

// 读取前4个字节
recv_len := 0
for recv_len < 4 {
    n, err := conn.Read(headBuf[recv_len:])
    if err != nil {
        conn.Close()
        return
    }
    recv_len = recv_len + n
}


来确保读取这么长的字节

我们看看修改后的服务器

image.png

image.png



修改后的客户端

image.png

image.png



编译服务器 和 客户端并且执行

先开启服务器,然后再启动客户端

查看服务器日志

image.png




思考


我们网络通信的方式,不管是客户端/服务器、P2P 还是 混合 , 其本质还是 客户端/服务器 通信,只不过后两者,在前者基础上做了改变而已。


我们实现通信使用的是套接字,套接字就是 ip+ 端口

而后我们实验了最简单的TCP服务器,引出了“粘包”的问题。而粘包的问题本质是: TCP连接是流,无法判断数据开头和结尾,从而导致粘包,而解决粘包的方式是,我们发送数据的时候,先获取待发送数据的长度,然后将长度和数据一起发过去,接收数据的时候,先接收长度,然后根据长度,接收实际数据,这样就能避免粘包。



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
网络协议 安全 测试技术
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
41 2
|
1月前
|
SQL 前端开发 Go
编程笔记 GOLANG基础 001 为什么要学习Go语言
编程笔记 GOLANG基础 001 为什么要学习Go语言
|
3月前
|
监控 Linux Shell
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(排查问题指令 - 下)
在线上排查问题时,查询日志、查看系统配置和分析操作系统信息是至关重要的。这些操作可以帮助我们深入了解软件和服务的兼容性,并解决潜在的问题。在本次学习中,我们将介绍并深入学习一些我在处理类似问题时常用的指令。通过掌握这些指令,你将能够更加高效地定位和解决线上问题,提高系统的稳定性和性能。让我们一同进入这个学习过程吧!
43 0
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(排查问题指令 - 下)
|
1月前
|
网络协议 Java
【开源视频联动物联网平台】J2mod库写一个Modbus TCP 服务器
【开源视频联动物联网平台】J2mod库写一个Modbus TCP 服务器
66 0
|
2月前
|
网络协议 Java API
【JavaEE初阶】 TCP服务器与客户端的搭建
【JavaEE初阶】 TCP服务器与客户端的搭建
|
2月前
|
安全 Shell 网络安全
Git学习---Git快速入门、Git基础使用、Git进阶使用、Git服务器使用(IDEA集成GitHub、Gitee、GitLab)、GitHub Desktop客户端
Git学习---Git快速入门、Git基础使用、Git进阶使用、Git服务器使用(IDEA集成GitHub、Gitee、GitLab)、GitHub Desktop客户端
131 0
|
2月前
|
数据采集 网络协议 搜索推荐
网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)
网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)
56 0
|
3月前
|
网络协议 安全 Linux
腾讯三面:一台服务器,最大支持的TCP连接数是多少?
一个 TCP 对象占用的大小,等于它所包含的一些数据结构占用大小的总和,也是就把上面这些数据结构的大小累加起来,就是一个 TCP 连接占用的大小了。实际过程中的 TCP 连接,肯定不是静止状态的,还会进行发送数据和接收数据了,那么这些过程还是会额外消耗更多的内存资源的,8 GB 物理内存的服务器实际并发很难达到百万级别。
60 2
|
3月前
|
网络协议 安全 Go
TCP基础详解:Telnet回音服务器搭建
TCP基础详解:Telnet回音服务器搭建
30 0
|
3月前
|
关系型数据库 Linux Shell
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(文件处理指令-上)
在当今的数字化时代,Linux已成为服务器、云计算、物联网等众多领域的核心操作系统。对于技术从业者、开发者以及系统管理员来说,掌握Linux指令不仅是一项基本技能,更是打开专业领域大门的关键。
50 3
【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(文件处理指令-上)