长连接,短连接,Socket通讯ping pong(长连接)

1.Socket读写数据:流Socket,数据包Socket?

  • 流套接字(SOCK_STREAM):
    (1)流套接字用于提供面向连接、可靠的数据传输服务。
    (2)该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。
    (3)流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission Control Protocol)协议。
  • 数据报套接字(SOCK_DGRAM):
    (1)数据报套接字提供了一种无连接的服务。
    (2)该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。
    (3)数据报套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据包套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
  • 原始套接字(SOCK_RAW):
    (1)原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,
    (2)而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。
    (3)因此,如果要访问其他协议发送数据必须使用原始套接字。

2.Socket类型,名字/常量 描述

  • SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个 socket是使用TCP来进行传输。
  • SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
  • SOCK_SEQPACKET 这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
  • SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
  • SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序

3.“烫烫烫”

  • socket接收数据长度设置记录:近期在项目中使用原先封装的socket库时发现当长度超过1024时,接收到的字符串会有“烫烫烫”的标志出现,之前有看过大神调侃的“烫烫烫屯屯屯”,直觉地想到应该是数组的长度部分设置有问题。检查代码发现,用于接收的buffer长度为1024,而在使用socket的recv函数中也将最大长度设置为了1024,同时将buffer中的数组拷贝出去的长度也为1024,因此该字符串中没有‘\0’的结束符,打印出来未初始化栈空间的值,也就出现了著名的"手持两把锟斤拷,口中疾呼烫烫烫。脚踏千朵屯屯屯,笑看万物锘锘锘"。
  • 将recv函数中最大长度设置为1023或者将buffer的长度改为1025即可解决,这样就也有结束符,也就不会出现上述现象了。

4.websocket

(1)WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。Comet技术又可以分为长轮询和流技术。

(2)websocket协议,长连接和Http短连接
WebSocket如何建立连接、交换数据的细节,以及数据帧的格式?

  • WebSocket复用了HTTP的握手通道。具体指的是,客户端通过HTTP请求与WebSocket服务端协商升级协议。
  • 协议升级完成后,后续的数据交换则遵照WebSocket的协议。

(3)websocket协议是基于tcp的网络协议,实现了浏览器与客户端的全双工通信,与http协议不同的是,它允许服务器主动推送消息给客户端。

(4) websocket协议分为两部分,一是握手建立连接;二是数据传输。
建立连接:websocket的连接建立是基于http协议的。
数据传输:websocket协议中数据是通过一系列的帧来传输。
出于安全性考虑,所有客户端发往服务器的数据帧需要掩码,若服务器收到未掩码的数据帧将会主动断开连接;所有服务器发往客户端的数据帧不能掩码,若客户端收到掩码的数据帧将会主断开连接。

5.长连接如何处理心跳机制?

(1)维护任何一个长连接都需要心跳机制,客户端发送一个心跳给服务器,服务器给客户端一个心跳应答,这样就形成客户端服务器的一次完整的握手,这个握手是让双方都知道他们之间的连接是没有断开,客户端是在线的

(2)如果超过一个时间的阈值,客户端没有收到服务器的应答,或者服务器没有收到客户端的心跳,那么对客户端来说则断开与服务器的连接重新建立一个连接,对服务器来说只要断开这个连接即可。

6.(websocket)协议中Ping Pong,长连接

(1)WebSocket为了保持客户端、服务端的实时双向通信,需要确保客户端、服务端之间的TCP通道保持连接没有断开。然而,对于长时间没有数据往来的连接,如果依旧长时间保持着,可能会浪费包括的连接资源。但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接。这个时候,可以采用心跳来实现。
发送方->接收方:ping;
接收方->发送方:pong;
ping、pong的操作,对应的是WebSocket的两个控制帧,opcode分别是0x9、0xA。

(2)websocket ping pong:目前的话,浏览器中没有相关api发送ping给服务器,只能由服务器发ping给浏览器,浏览器返回pong消息;

(3)WebSocket控制帧有3种:Close(关闭帧)、Ping以及Pong。
控制帧的操作码定义了0x08(关闭帧)、0x09(Ping帧)、0x0A(Pong帧)。Close关闭帧很容易理解,客户端如果接受到了就关闭连接,客户端也可以发送关闭帧给服务端。
Ping和Pong是websocket里的心跳,用来保证客户端是在线的,一般来说只有服务端给客户端发送Ping,然后客户端发送Pong来回应,表明自己仍然在线。

7.WebSocket分包,粘包,连包,半包

(1)网上很多资料都说WebSocket不会粘包,半包。OK,这是正确的,因为上述将数据帧的时候我们已经看到WebSocket会将大的数据,自动分片发送。所以WebSocket会自动分包发送,因为这种分包发送,WebSocket的数据不会溢出接收缓冲区,所以也不会有半包的情况发送。

(2)但是关于粘包,和连包,我看到一部分资料都说不会。因为WebSocket具有帧头信息,所以不会粘包?
这是不完全正确的,要知道Tcp的报文也是具有包头信息的,只不过Socket已经处理了。而且经过我对我们项目服务器实际压力测试,发现WebSocket会粘包,连包。不同的是,WebSocket的数据中拥有包头信息,但Tcp没有(实际开发中,我们自己一定会加个包头来分割封包的,WebSocket只是替我们设计了一个包头而已),但对这个包头分割的处理,还是要我们自己完成,WebSocket不会代劳,如果我们自己不处理,抱歉,妥妥的粘包,连包

8.Socket通讯ping pong

  • Socket默认是长链接,为了知道Client和Server链接是否正常,项目中使用的ClientSocket和ServerSocket都有一个心跳的线程,这个线程主要是为了检测Client和Server是否正常链接,Client和Server是否正常链接主要是用ping pong流程来保证的.

9.http的长连接和短连接的概念

(1)http协议有短连接和长连接的概念:

  • 短连接就是指客户端(浏览器)每次请求都会建立一个连接,即每次连接都要完成三次握手,释放时要四次挥手。
  • 对应的,长连接就是指多次请求复用同一个连接,以达到提高效率的目的。
  • 对于短连接,服务器要主动断开连接,否则浏览器会一直等待(这是经过测试得知的,那么为什么浏览器不能主动关闭呢?)。而对于长连接尽量不要主动断开连接,为什么呢?这涉及到tcp连接的状态,主动断开的连接会有一个TIME_WAIT的状态, 这个状态会持续2MSL的时间(各个系统根据参数实现的不同,通常为2min),这会影响高并发时的性能。因此最好在客户端断开连接。

(2)那客户端什么时候断开呢?

  • 由服务器去通知行的通吗?可以这样,超过一定时间后,下次回复客户端时设置Connection: close标识,这样客户端就会主动断开了。
  • 如果服务器没有下次回复的机会,那么只有等待客户端主动断开连接了。客户端超时是会主动关闭的,在360浏览器上测试是110s(这个时间不是从第一次连接开始计时的,而是空闲连接时间)。如果客户端没有超时断开机制,那只能在服务器做超时处理,然后主动断开了。

10.如何快速区分长连接和短连接

(1)凡是在一次完整的消息交互(发请求-收响应)之后,立刻断开连接(有一方发送FIN消息)的情况都称为短连接;
(2)长连接的一个明显特征是会有心跳消息(也有没有心跳的情况),且一般心跳间隔都在30S或者1MIN左右,用wireshark抓包可以看到有规律的心跳消息交互(可能会存在毫秒级别的误差)。

11. 什么时候用长连接,短连接?

(1)需要频繁交互的场景使用长连接,如即时通信工具(微信/QQ,QQ也有UDP),相反则使用短连接,比如普通的web网站,只有当浏览器发起请求时才会建立连接,服务器返回相应后,连接立即断开。
(2)维持长连接会有一定的系统开销,用户量少不容易看出系统瓶颈,一旦用户量上去了,就很有可能把服务器资源(内存/CPU/网卡)耗尽,所以使用需谨慎。

参考:

https://blog.csdn.net/ShareUs/article/details/85246287
https://blog.csdn.net/zxm342698145/article/details/90547691
https://www.cnblogs.com/pangguoping/p/5571422.html
下面是一个简单的Java Socket长连接心跳检测代码示例: ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class SocketClient { public static void main(String[] args) { String host = "localhost"; int port = 8080; try { Socket socket = new Socket(host, port); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); while (true) { // 发送心跳包 out.write("ping".getBytes()); out.flush(); // 等待服务器响应 byte[] buffer = new byte[1024]; int len = in.read(buffer); if (len == -1) { System.out.println("Server closed connection."); break; } String response = new String(buffer, 0, len); if ("pong".equals(response)) { System.out.println("Received pong from server."); } else { System.out.println("Received unknown response from server: " + response); } // 等待一段时间再次发送心跳包 Thread.sleep(5000); } } catch (IOException e) { System.out.println("Error connecting to server: " + e.getMessage()); } catch (InterruptedException e) { System.out.println("InterruptedException occurred: " + e.getMessage()); } } } ``` 在这个示例中,客户端向服务器发送一个字符串"ping"作为心跳包,然后等待服务器响应。如果服务器响应了"pong",客户端会打印出"Received pong from server.",否则会打印出"Received unknown response from server:" 加上收到的响应内容。在等待一段时间(这里是5000毫秒)之后,客户端会再次发送心跳包。如果服务器关闭了连接,客户端会退出循环并打印出"Server closed connection."。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值