服务器基础知识
TouchSocket说明文档。 TouchSocket | TouchSocket (gitee.io)
Socket
socket的英文原义是“孔”或“插座”。作为进程通信机制,取后一种意思。通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄(其实就是两个程序通信用的)。
socket非常类似于电话插座。以一个电话网为例:
- 电话的通话双方相当于相互通信的2个程序,电话号码就是IP地址。
- 任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;
- 同时要知道对方的号码,相当于对方有一个固定的socket。
- 然后向对方拨号呼叫,相当于发出连接请求。
- 对方假如在场并空闲,拿起电话话筒,双方就可以正式通话,相当于连接成功。
- 双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。
- 通话结束后,一方挂起电话机相当于关闭socket,撤销连接。
端口
在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务。
每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应用程序),因此,在网络协议中使用端口号识别主机上不同的进程。
例如:http使用80端口,FTP使用21端口。
协议
TCP与UDP:
- UDP可靠性不如TCP
TCP包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其他信息,否则将一直等待直到收到确认信息为止。与TCP不同,UDP并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP称为不可靠的传输协议。 - TCP在开始建立通讯时,为了保证可靠性需要先进行“三次握手”之后才进行信息传输。
- UDP不能保证有序传输
UDP不能确保数据的发送和接收顺序。对于突发性的数据报,有可能会乱序。
Socket通信基本流程
上图中的服务器“Accept”部分不全面,服务器面对客户端大量的Socket链接有同步、异步、多路复用等方式
服务器端:
第一步:创建一个用于监听连接的Socket对像;
第二步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第三步:用socket对像的Bind()方法绑定EndPoint;
第四步:用socket对像的Listen()方法开始监听;
第五步:接收到客户端的连接,用socket对像的Accept()方法创建一个新的用于和客户端进行通信的socket对像;
第六步:通信结束后一定记得关闭socket;
客户端:
第一步:建立一个Socket对像;
第二步:用指定的端口号和服务器的ip建立一个EndPoint对像;
第三步:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求;
第四步:如果连接成功,就用socket对像的Send()方法向服务器发送信息;
第五步:用socket对像的Receive()方法接受服务器发来的信息 ;
第六步:通信结束后一定记得关闭socket;
Socket链接方式
同步Socket
阻塞式。纯采用阻塞式,这种方式很少见,基本只会出现在demo中。多个描述符需要用多个进程或者线程来一一对应处理。
异步Socket
大部分客户端都使用异步Socket。需要注意的是,Unity的大部分原生逻辑不能使用异步执行,所以客户端的异步Socket需要缓存在队列中再同步执行。
非阻塞式。纯非阻塞式,对IO的就绪与否需要在用户空间通过轮询来实现。
多路复用Select
【面试】彻底理解 IO多路复用_Hollis Chuang的博客-CSDN博客
当我们讨论异步 IO模型的时候,讨论的对象到底是什么? - 知乎 (zhihu.com)
服务器使用多路复用,当服务器和客户端互相发送接收信息的过程中,某些客户端暂时中断发送(但是TCP没有断开)时,服务器接收并处理其他客户端的信息,将资源最大限度地分配,提高CPU效率:
IO多路复用+阻塞式。仅使用一个线程就可以实现对多个描述符的状态管理,但由于IO输入输出调用本身是阻塞的,可能出现某个IO输入输出过慢,影响其他描述符的效率,从而体现出整体性能不高。此种方式编程难度比较低。
IO多路复用+非阻塞式。在多路复用的基础上,IO采用非阻塞式,可以大大降低单个描述符的IO速度对其他IO的影响,不过此种方式编程难度较高,主要表现在需要考虑一些慢速读写时的边界情况,比如读黏包、写缓冲不够等。
SocketAsyncEventArgs
基于Socket低层实现的高效链接方式,在大型商业项目中会使用。
微软官方文档中的SocketAsyncEventArgs
服务器SocketAsyncEventArgs
TouchSocket说明文档。 TouchSocket | TouchSocket (gitee.io)
Socket多路复用
IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题,此外poll、epoll都是这种模型。
在该种模式下,服务器首先将需要进行IO操作的socket添加到select中,然后阻塞等待内核select系统调用返回。当数据到达时,socket被激活,select函数返回。服务端线程正式发起read请求,读取数据并继续执行。
从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是服务端可以在一个线程内同时处理多个socket的IO请求。服务端可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。
课程使用的Socket模型
数据库
课程使用Mysql,Mysql的ORM使用SqlSugar。
数据库ORM(Object Relational Mapping)是一种将对象编程思维应用于关系型数据库的技术。它通过将数据库表映射为编程语言中的类,以及将表中的字段映射为类的属性,来实现对象与关系型数据库之间的数据交互。这种技术使得开发人员能够以面向对象的方式操作数据库,提高了开发效率和数据访问的抽象程度。
数据库ORM的主要优点包括:
- 提高开发效率:ORM自动对Entity对象和数据库表进行字段与属性的映射,减少了手动编写SQL语句的工作量。
- 抽象化数据访问:ORM提供了对数据库的映射,使得开发人员能够像操作对象一样获取数据,而无需关心具体的SQL语句。
然而,ORM也存在一些缺点:
- 程序执行效率降低:由于ORM引入了更多的抽象层,会导致程序执行效率降低。
- 固定思维模式限制:ORM可能会限制开发人员的思维创新,使得他们更依赖于框架提供的特性,而忽视了数据库本身的优化可能性。
- 数据库特性无法完全利用:ORM可能无法充分利用数据库本身的特性,例如存储过程、触发器等。
在选择使用ORM框架时,需要根据项目的具体需求和数据库特性进行综合考虑。
注意
在服务器开发过程中,只要是主动调用的方法,都需要用try……catch块包裹。