精华内容
下载资源
问答
  • tcp长连接和短连接
    2021-05-31 21:12:11


    TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次握手,所以说每个连接的建立都是需要资源消耗和时间消耗的。

    1. TCP短连接

    模拟一种TCP短连接的情况:

    client 向 server 发起连接请求
    server 接到请求,双方建立连接
    client 向 server 发送消息
    server 回应 client
    一次读写完成,此时双方任何一个都可以发起 close 操作
    

    在步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。

    从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!

    2. TCP长连接

    再模拟一种长连接的情况:

    client 向 server 发起连接
    server 接到请求,双方建立连接
    client 向 server 发送消息
    server 回应 client
    一次读写完成,连接不关闭
    后续读写操作...
    长时间操作之后client发起关闭请求
    

    3. TCP长/短连接操作过程

    3.1 短连接的操作步骤

    建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接

    3.1 长连接的操作步骤

    建立连接——数据传输…(保持连接)…数据传输——关闭连接

    4. TCP长/短连接的优点和缺点

    长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。但是,client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损; 如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。

    短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

    5. TCP长/短连接的应用场景

    数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

    WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那后果可想而知。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

    更多相关内容
  • 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接连接的建立是需要三次握手的,而释放则需要4次挥手,所以...

         当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次挥手,所以说每个连接的建立都是需要资源消耗和时间消耗的

     示意图:

                                                

                                                    

     

    长连接

           所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(不发生RST包和四次挥手)。      

    连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接(一个TCP连接通道多个读写通信); 

          这就要求长连接在没有数据通信时,定时发送数据包(心跳),以维持连接状态

          TCP保活功能,保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务器端检测到这种半开放的连接

           如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:

    1. 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。
    2. 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接
    3. 客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。
    4. 客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。

    短连接:

          短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接(管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段);

    连接→数据传输→关闭连接;

     

    应用场景:

         长连接多用于操作频繁(读写),点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

         而像WEB网站的http服务一般都用短链接(http1.0只支持短连接,1.1keep alive 带时间,操作次数限制的长连接),因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好;

     

         在长连接中一般是没有条件能够判断读写什么时候结束,所以必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读相应长度的报文。

     

     参考:http://www.cnblogs.com/qqzy168/p/3141703.html

             http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html

     


    转载自:https://www.cnblogs.com/onlysun/p/4520553.html

    展开全文
  • TCP 长连接和短连接

    2021-05-31 13:40:47
    TCP长连接和短连接的区别: 连接: 1.指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(不发生RST包和四次挥手)。 2....

    参考文章:

    长连接:

    RUNOOB 图标

    1. 介绍
      指在一个TCP连接上可以连续发送多个数据包。在TCP连接保持期间,如果没有数据包发送,需双方发送探测包以维持此连接,一般需要自己做在线维持(不发送RST包和四次挥手)。
    2. 过程:

    连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接(一个TCP连接通道多个读写通信)。 这就要求长连接在没有数据通信时,定时发送数据包(心跳),以维持连接状态;

    1. 应用场景:
      数据库,各种组件的连接等…
      长连接多用于操作频繁(读写),点对点的通讯,且连接数不能太多的场景。因为频繁建立tcp连接,是对资源的浪费,服务器的请求处理速度也会更低。
    2. 优点:
      长连接可以省去较多的TCP建立和关闭的操作(三次握手/四次挥手),减少资源浪费,节约连接时间。对于频繁请求资源的客户来说,更适用长连接。
    3. 缺点:
      client与server间的连接如果一直不关闭,会存在一个问题:随着客户端连接越来越多,server早晚有扛不住的时候,这时server端需要采取一些策略:
      • 如关闭一些长时间没有产生读写事件的连接,这样能淘汰一些导致server端服务受损的恶意连接
      • 如果条件再允许就以客户端机器为粒度,限制每个客户端的最大长连接数,这样能避免某个客户端占据大量后端服务连接
    4. 问题:

      (1) HTTP首部定义Connection: keep-alive后,客户端、服务端怎么知道本次传输结束呢?
      在长连接中一般是没有条件能判断读写何时结束,又因为tcp首部中没有直接表示数据包长度的字段,所以要获取tcp数据包长度,可通过ip首部及tcp首部获取:TCP数据包长度 = IP首部的数据包长度 - IP首部长度(20字节 )- TCP包首部长度(20字节 ),最后根据这个长度去读取相应长度的报文。

      静态页面通过Content-Length提前告知对方数据传输大小。

      (2) 客户端是长连接还是短连接?

      推荐长连接。若业务并发量大,为性能考虑,可以开启『连接池』功能。(连接池:由于一些数据库创建和销毁连接的开销很大,或者相对于所执行的具体数据操作,连接所耗的资源过多,此时就需要添加连接池改善性能。它是一些网络代理服务或者应用服务器实现的特性,这个连接池被所有连接的客户端共享使用,连接池可以加速连接,也可以减少数据库连接,降低数据库服务器的负载)。

    5. 补充:
    • 在http中,设置header的Connection为keep-alive就算是长连接了,但是要服务器和客户端两边都设置才有效。(如果客户端的请求头中的connection为close,则表示客户端需要关掉长连接)
    • 日常用的基本上都是HTTP1.1协议(默认长连接,也就是默认Connection的值就是keep-alive)
    • 长连接并不是永久连接的。如果一段时间内(具体的时间长短,是可以在header当中keepalive_timeout进行设置的,也就是超时时间),超时的话这个长连接就会被断开。
      请求头字段

    短连接:

    RUNOOB 图标

    1. 介绍:
      通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接(管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段);
    2. 过程:

    连接 → 数据传输 → 关闭连接

    1. 应用场景:
      WEB网站的http服务一般都用短链接(http1.0默认为短连接,而http1.1之后默认为长连接,keep-alive 带时间,操作次数限制的长连接),因为长连接对于服务端来说会耗费一定的资源,而像WEB
      网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源(也就是正常情况下,每个用户不会频繁发送请求,没必要长时间占用一条连接或端口)
    2. 优点:
      短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段
    3. 缺点:
      如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽,消耗服务端的资源
    展开全文
  • TCP长连接和短连接代码及其比较

    千次阅读 2020-08-02 13:49:43
    前言: 最近又看到了关于TCP长连接和短连接的概念,以前也看过Http长连接和短连接的概念,因为Http是建立在TCP协议之上的,所以它其实是依赖TCP长连接和短连接。所以,我就萌生了一个想法,看看这两种方式的传输...

    前言: 最近又看到了关于TCP长连接和短连接的概念,以前也看过Http长连接和短连接的概念,因为Http是建立在TCP协议之上的,所以它其实是依赖TCP的长连接和短连接。所以,我就萌生了一个想法,看看这两种方式的传输效率上到底有多大差别——实践出真知!或者 Takl is cheap, show me your code!

    TCP长连接和短连接

    长连接是指可以实现服务端和客户端之间连续的传输数据,在传输的过程中,连接保持开启,并不中断,数据传输完成后连接不关闭。
    短连接是指当服务器端和客户端连接成功后开始传输数据,传输完成即关闭连接。如果需要再次传输数据,则需要在创建新的连接进行数据传输。

    如果你没有系统的学习过计算机网络的话,可能感觉这样似乎没有什么区别,这里我简单说明一下:
    传输时间 = 建立连接的时间 + 传输数据的时间

    TCP 建立连接需要进行三次握手,如果频繁的传输数据并且采用短连接的形式,则会频繁的建立连接,降低了传输效率。但是如果采用长连接的形式,则只需要建立一次连接,就可以传输多次数据了。当然了,好处有,坏处也是少不了的。短连接传输完成即关闭,服务器不需要保存连接对象,对于服务器的压力较小;长连接则需要保持多个连接对象(很多客户一起使用,需要保持他们的连接),对于服务器的压力较大,并且长连接如何处理数据也是一个问题了——传输数据本质上就是字节流,如果连续的传输字节流,你如何知道哪一部分是属于哪一个文件的呢?

    如果你对这个问题,感兴趣的可以参考我这篇博客,应该会对你有一些启发,这是我个人的一种解决方案。
    单个TCP(Socket)连接,发送多个文件

    测试用例

    我这里使用六个图片文件作为测试,对于短连接就是连续发送六次数据;对于长连接是发送一次数据。
    在这里插入图片描述
    测试图片的大小
    在这里插入图片描述

    TCP 短连接测试

    TCP短连接客户端

    package short_tcp;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class ShortClient {
    	private static final String host = "127.0.0.1";
    	private static final int port = 10000;
    	
    	public static void main(String[] args) {
    		// 存放需要传输文件的目录
    		Path path = Paths.get("D:", "DragonFile", "tcp", "targetFile");
    		// Files.find() 和 walk() 方法似乎使用起来更加简单,但是它传递的参数,
    		// 我暂时还不清楚,那就不用了,免得引入额外的麻烦。
    		File dir = path.toFile();
    		// 获取该目录下的所有文件
    		File[] files = dir.listFiles();
    		// 创建短连接客户端对象
    		ShortClient shortClient = new ShortClient();
    		// 连续发送6个文件
    		System.out.println("Start data transfer...");
    		long start = System.currentTimeMillis();
    		for (File file : files) {
    			shortClient.send(file);
    		}
    		System.out.println("6个文件使用tcp短连接的方式发送结束,总耗时:" + (System.currentTimeMillis()-start) + " ms。");
    		System.out.println("End of data transmission!");
    	}
    	
    	public void send(File file) {
    		// 创建一个 Socket 客户端
    		try (Socket client = new Socket(host, port)) {
    			// 获取输出流,用于发送数据
    			OutputStream output = new BufferedOutputStream(client.getOutputStream());
    			// 获取输入流,用于接收服务器的响应数据
    			InputStream input = new BufferedInputStream(client.getInputStream());
    			// 每次实际读取到的字节数
    			int len = 0;
    			// 每次读取1024字节的数据
    			byte[] b = new byte[1024];
    			// 创建一个文件输入流,用于获取文件数据,并使用输出流发送到服务器
    			try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
    				while ((len = in.read(b)) != -1) {
    					output.write(b, 0, len);
    				}
    				// 强制刷新输出流,防止阻塞
    				output.flush();
    			}
    			// 关闭输出流,注意可不能使用 output.close()!它会把整个套接字关闭的!
    			// 关于它会不会刷新输出流,我没有找到资料,当我感觉应该是会的,但是感觉不靠谱,
    			// 上面我仍然手动刷新输出流吧!
    			client.shutdownOutput(); 
    			// 读取服务器的响应信息
    			len = input.read(b);
    			// 注意如果 len 为 -1,会导致 RunTimeException
    			System.out.println(new String(b, 0, len, StandardCharsets.UTF_8));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    

    TCP短连接服务端

    package short_tcp;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.util.UUID;
    
    public class ShortServer {
    	private static final int port = 10000;
    	
    	public static void main(String[] args) {
    		new ShortServer().start();
    	}
    	
    	public void start() {
    		try (ServerSocket server = new ServerSocket(port)) {
    			// 这里不使用多线程,因为我主要关注点在于创建socket连接的开销
    			while (true) {
    				System.out.println("Waitting for client to connect...");
    				try (Socket client = server.accept()) {
    					InputStream input = new BufferedInputStream(client.getInputStream());
    					OutputStream output = new BufferedOutputStream(client.getOutputStream());
    					/* 统一使用 .jpg 扩展名了,这里要指明一点,由于传输的只是文件的数据部分,
    					 * 所以我是无法知道该使用什么扩展名的,当然了,是可以把其它信息传输过来,
    					 * 但是那样处理回麻烦一点。
    					 * */
    					// 使用 UUID 生成随机的文件名
    					String filename = UUID.randomUUID().toString() + ".jpg";
    					// 实际读取到的字节数
    					int len = 0;
    					// 每次读取1024字节
    					byte[] b = new byte[1024];
    					// 创建一个输出流,保存接收到的文件数据
    					try (OutputStream out = new BufferedOutputStream(new FileOutputStream(
    							new File("D:/DragonFile/tcp/short_tcp", filename)))) {
    						// 我在客户端使用了关闭了输出流,这里是可以使用 -1 来判断的!
    						while ((len = input.read(b)) != -1) {
    							out.write(b, 0, len);
    						}
    						// 这里不需要手动刷新,因为 try-with-resource 
    						// 语句会自动关闭流,而关闭流的时候,会调用flush方法的。
    						// 注意这些细节问题。
    					}
    					output.write("The data has been received successfully".getBytes(StandardCharsets.UTF_8));
    					output.flush();     // 如果这里不进行手动刷新,会导致客户端读取到 -1 的异常!
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    说明:关于这部分的代码,就是很普通的socket传输文件,只是调用多次,传输多个文件而已。只要是学习过Socket网络编程的,基本上都没有问题了。

    测试结果

    服务器端
    在这里插入图片描述

    客户端
    在这里插入图片描述

    说明
    第一次建立Socket连接的过程不算,因为它耗时太多了,但主要并不是传输的时间。我们看后面三次,分别是25ms、25ms、25ms,平均时间也就是25ms了我这里不是精确计算,只能做一个大致的估计。

    传输文件结果
    在这里插入图片描述
    传输文件的大小
    这里只看总的大小了(虽然应该看每一个的大小或者md5值,但是应该还是没有问题的!)
    在这里插入图片描述

    TCP 长连接测试

    这里长连接,就是一次性把六个文件的数据,通过一次连接传输过去,多个文件一起传输,如果不携带额外的控制信息的话,那么文件传输是没有意义的,因为谁也无法从字节流里面把文件分出来,这是一个数学上的问题了。不过它和我以前这篇博客倒是有些相似了,如果只有你自己知道,就可以去做一些有趣的事情了。文件合并(图片+视频),修改md5值,隐藏文件

    所以,需要除了文件本身的字节数据以外的控制信息,这里我定义一个简单的协议。协议包含一个头部和数据部分,头部是8个字节的长度信息,数据部分就是相应长度的数据信息了。它很简单,不过在这里也足够用了。 具体可以参考我最上面推荐的博客,并且我的注释也写得很详细了。

    协议图示

    TCP长连接客户端

    package long_tcp;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class LongClient {
    	private static final String host = "127.0.0.1";
    	private static final int port = 10000;
    	
    	public static void main(String[] args) {
    		// 存放需要传输文件的目录
    		Path path = Paths.get("D:", "DragonFile", "tcp", "targetFile");
    		File dir = path.toFile();
    		// 获取该目录下的所有文件
    		File[] files = dir.listFiles();
    		// 创建长连接客户端对象
    		LongClient longClient = new LongClient();
    		System.out.println("Start data transfer...");
    		long start = System.currentTimeMillis();
    		longClient.send(files);
    		System.out.println("6个文件使用tcp长连接的方式发送结束,总耗时:" + (System.currentTimeMillis()-start) + " ms。");
    		System.out.println("End of data transmission!");
    	}
    	
    	public void send(File[] files) {
    		try (Socket client = new Socket(host, port)) {
    			// 获取输出流,用于发送数据
    			OutputStream output = new BufferedOutputStream(client.getOutputStream());
    			// 获取输入流,用于接收服务器的响应数据
    			InputStream input = new BufferedInputStream(client.getInputStream());
    			// 每次实际读取到的字节数
    			int len = 0;
    			// 每次读取1024字节的数据
    			byte[] b = new byte[1024];
    			for (File file : files) {
    				// 获取文件的长度
    				long length = file.length();
    				// 先将文件的长度写入socket
    				output.write(this.long2Byte(length));
    				try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
    					// 然后写入文件数据
    					while ((len = in.read(b)) != -1) {
    						output.write(b, 0, len);
    					}
    				}
    				// 手动刷新输出流
    				output.flush();
    				// 读取服务器响应
    				len = input.read(b);
    				// 打印服务器响应数据
    				System.out.println(new String(b, 0, len, StandardCharsets.UTF_8));
    			}
    			// 关闭输出流
    			client.shutdownOutput();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    	// 使用长度为8个字节的数组保存long的值
    	public byte[] long2Byte(long length) {
    		byte[] b = new byte[8];
    		b[0] = (byte) (length >>> 56);
    		b[1] = (byte) (length >>> 48);
    		b[2] = (byte) (length >>> 40);
    		b[3] = (byte) (length >>> 32);
    		b[4] = (byte) (length >>> 24);
    		b[5] = (byte) (length >>> 16);
    		b[6] = (byte) (length >>> 8);
    		b[7] = (byte) (length >>> 0);
    		return b;
    	}
    }
    
    

    TCP长连接服务端

    package long_tcp;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    import java.util.UUID;
    
    public class LongServer {
    	private static final int port = 10000;
    	
    	public static void main(String[] args) {
    		new LongServer().start();
    	}
    	
    	public void start() {
    		try (ServerSocket server = new ServerSocket(port)) {
    			// 这里因为只有一次连接,我其实是不需要使用死循环的,但是为了保证统一,还是使用吧
    			while (true) {
    				System.out.println("Waitting for client to connect...");
    				try (Socket client = server.accept()) {
    					InputStream input = new BufferedInputStream(client.getInputStream());
    					OutputStream output = new BufferedOutputStream(client.getOutputStream());
    					// 读取8个字节的长度,这里因为情况比较特殊,它是一定能读取到8个头的,
    					// 至于其它情况,暂时不考虑,就认为它一定能读取完整的8个字节,但是下面的1024就不一定了。
    					byte[] head = new byte[8];
    					// 读取数据部分
    					byte[] data = new byte[1024];
    					// 这里使用一个死循环来读取,记得要正确退出!
    					while (true) {
    						// 我这里认为它一定可以读取满8个字节的,因为我是本机测试,基本上没有问题的,
    						// 对于特殊的情况,我们不去考虑它,注意我们的关注点是传输的效率问题!
    						if (input.read(head) == -1) {
    							break;  //如果为 -1,说明流已经关闭了
    						}
    						// 我这里转成int,因为我测试使用的图片不是太大,这样处理也方便一些
    						int length = (int) byte2Long(head);
    						System.out.println("length:" + length);
    						String filename = UUID.randomUUID().toString() + ".jpg";
    						try (OutputStream out = new BufferedOutputStream(new FileOutputStream(
    								new File("D:/DragonFile/tcp/long_tcp", filename)))) {
    							int len = 0;
    							int hasRead = 0;
    							while ((len = input.read(data)) != -1) {
    								out.write(data, 0, len);
    								hasRead += len;
    								// 当文件最后一部分不足1024时,直接读取此部分,然后结束,文件已经读取完成了。
    								int remind = length - hasRead;
    								if (remind < 1024 && remind > 0) {
    									byte[] b = new byte[remind];
    									len = input.read(b);  // 这里没有特殊原因,它也是可以读取remind长度的。
    									out.write(data, 0, len);
    									System.out.println("remind:" + remind + " len:" + len);
    									break;   // 一个文件的数据已经读取完成了,及时退出该次读取
    								} else if (remind == 0) {
    									// 这里我有点疏忽了,没有考虑,文件小于1024字节时的读取
    									break;
    								}
    							}
    							// 响应客户端接收文件成功的数据
    							output.write("The data has been received successfully".getBytes(StandardCharsets.UTF_8));
    							output.flush(); // 刷新输出流
    						}
    					}
    					
    				}
    			}	
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public long byte2Long(byte[] b) {		
    		return (((long)b[0] << 56) +
                    ((long)(b[1] & 255) << 48) +
                    ((long)(b[2] & 255) << 40) +
                    ((long)(b[3] & 255) << 32) +
                    ((long)(b[4] & 255) << 24) +
                    ((b[5] & 255) << 16) +
                    ((b[6] & 255) <<  8) +
                    ((b[7] & 255) <<  0));
    	}
    }
    
    

    测试结果

    客户端
    在这里插入图片描述

    服务端
    注:这里我额外打印了获取到的文件的长度,因为长连接的处理比较麻烦,稍微有些问题没考虑到就不行了。
    在这里插入图片描述
    传输的文件
    注意:不要看到文件就认为成功了,文件的大小也必须是一样的,即传输前和传输后的大小是一样的,更为严格的要求是文件的md5值是一样的,我这里为了简单期间就只看大小了。
    传输的文件
    在这里插入图片描述
    传输文件的大小
    在这里插入图片描述

    说明
    第一次建立Socket连接的过程不算,因为它耗时太多了,但主要并不是传输的时间。我们看后面三次,分别是23ms、22ms、25ms,平均时间也就是23.33ms了我这里不是精确计算,只能做一个大致的估计。

    结果分析

    对于第一次建立连接发送数据,时间都是非常长的。但是对于这里到底是哪里耗时这么多,我暂时也不太清楚,它可能属于底层连接的问题了。我只比较后面三次的时间,但是感觉似乎差距也不是很大,顶多也就快了1ms多,但是它实在是太小了,让人觉得似乎长连接的效率也就是那样了!按照我一开始的理解,它应该会有一定的效率提升的。 所以,一定是哪里设计的不够合理,让我们来分析一下,对于整个传输过程来说,耗时主要是建立连接+传输数据了。但是如果数据量特别大,那它所占据的耗时百分比就越大,所以我这里传输的文件似乎太大了。反而掩盖了长连接所带来的减少建立连接的时间。比如传输10m文件,无论是长连接还是短连接效率上应该都是没有什么区别了,特别是网络特别慢的情况下,整个耗时都可以看做是传输耗时了,对于建立连接的耗时可以忽略不计了! 而且长连接其实还是比短连接多传输了一些控制信息,不然它是无法处理一个数据流为多个文件的。

    新的测试文件

    文件内容:
    看我引经据典来写几句话吧,哈哈。
    在这里插入图片描述
    文件大小:
    这次文件是很小了,保证了一次即可传输完成,这样应该就可以突出建立连接的时间了。
    在这里插入图片描述

    复制一下,还是传输六个文件
    在这里插入图片描述

    TCP短连接测试结果

    这次我除了第一次外,再测试五次,然后统计这五次的平均时间。
    在这里插入图片描述
    在这里插入图片描述
    总时间:17ms + 18ms + 19ms + 20ms + 18ms = 92ms
    平均时间:92ms/5 = 18.4ms

    TCP长连接测试结果

    在这里插入图片描述
    在这里插入图片描述
    总时间:14ms + 16ms + 17ms + 17ms + 16ms = 80ms
    平均时间:80ms/5 = 16ms

    总结

    这里虽然使用了小文件,但是似乎效果也不是很理想,因为我可能没有考虑到在本机进行环回测试,其实网速是很快的,所以其实我上面的图片也不算是大文件了。不过,我使用大文件效果是更不理想的,这样也算是可以了。
    通过上面的比较,可以发现:平均每次传输可以减少2ms的时延,大概提高了 2ms/18ms = 11%。当然了,随着文件的增大,整个效率是会逐渐减少的,甚至于没什么效果了。但是,我们这里是应该可以认为,长连接确实是可以提高一定的效率的,特别是在含有大量的连接,但是传输的数据量特别少的情况下,它是很有效的,特别是某些应用广泛的协议——HTTP协议。 通常使用HTTP的客户端,都是属于数据量很小的传输,我想效果应该是有的,虽然长连接的处理也比较麻烦了。

    PS:
    比如,当我传输小文件时,代码无法正常工作了,直接卡死了。所以我就把服务器关闭了,最后传输花费了20357ms。问题主要出在在字节流中取出一个文件时发生的,我的注释里面写了详细情况,也可以看我推荐的博客。长连接的处理比较麻烦,我这里是一种简化的模拟,但是也要面对一些不好处理的问题!
    在这里插入图片描述

    展开全文
  • 什么是长连接和短连接 1.官方解释 连接(long connnection),指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。 短连接(short connnection),是相对于连接...
  • TCP长连接和短连接区别

    千次阅读 2020-03-02 11:19:18
    短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接, 2.连接 连接->传输数据->保持连接->传输数据->....->关闭连接 连接指建立TCP连接后不管是否使用都...
  • tcp长连接和短连接TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次握手,所以说每个连接的...
  • 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接连接的建立是需要三次握手的,而释放则需要4次挥手,所以...
  • TCP长连接与短连接示意图
  • TCP 长连接和短连接

    2018-05-23 16:23:55
    HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接TCP连接和关闭:https://blog.csdn.net/qq_35546040/article/details/80280900 1.概念 TCP短连接:(在HTTP/1.0中,默认使用的是短连接。) ...
  • 刚接触HTTP请求就听说过HTTP请求有1.01.1两个版本(其实还有个0.9版本,因为只接受GET一种请求,不支持POST方法,因此客户端无法向服务器传递太多信息而为人们所忽略),而且还知道HTTP1.0协议不支持长连接,从...
  • 最近开发中遇到以下:需要客户端建立一个链接,然后服务器端持有这个链接,当有时间变换(如任务的...在思考这个问题时,我就在想Http建立的TCP短连接,是什么时候断开连接的?基于这个问题,我就写了个简单的测试用...
  • 1. TCP短连接我们模拟一下TCP短连接的情况,client向server发起连接请求,server接到请求,然后双方建立连接。client向server发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close...
  • TCP长连接和短链接的区别及应用场景 TCP在真正的读写操作之前,服务端与客户端之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次挥手...
  • TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接... TCP短连接模拟一种TCP短连接的情况:client 向 server 发起连接请求server 接到请求,双方建立连接client...
  • 目录 ...3. 什么是连接、短连接? 3.1 TCP连接 3.2 TCP短连接 3.3 TCP连接 3.4连接短连接操作...4. 长连接和短连接的优点和缺点 5. 什么时候用连接,短连接? 6、容易混淆的概念(TCP的keep alive和HT...
  • 所以说,每个TCP连接的建立释放都是需要消耗资源时间成本的。 二 TCP短连接 模拟一种TCP短连接的情况: client 向 server 发起连接请求 server 收到连接请求,双方建立TCP连接 client 向 server 发送消息 ...
  • TCP长连接和短连接

    2022-04-18 00:25:21
    这次之所以能在这么的时间里搞清楚,自己技术的沉淀密不可分。因此,这里借着这个机会,再次强调一下,千万不要试图去研究你研究了很久都整不明白的东西,或许是你的层次不到,也或许是你从未在实际的应用场景...
  • 基于Apache Mina实现的TCP长连接和短连接实例 详细说明,可参见blog http://blog.csdn.net/peterwanghao/article/details/6900523
  • 导读tcp长连接和短连接TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立通过三次握手,释放则需要四次握手,所以说每个...
  • tcp长连接和短连接

    千次阅读 2018-11-30 08:26:50
    TCP在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这...1. TCP短连接 模拟一种TCP短连接的情况: 1. client 向 server 发起连接请求 2. serve...
  • TCP三次握手,4次挥手,tcp的十种状态,2msl以及短连接和长连接
  • TCP长短连接简单Demo

    2018-12-29 16:38:50
    C++ 实现 TCP长,短连接简单Demo,基于VS2017
  • TCP链接和长连接

    千次阅读 2022-03-28 10:59:09
    在写网络编程项目的客户端的时候,出现了这样的疑问。在什么时候连接上服务器呢?...在我的认识里,TCP短连接和长连接的区别主要是三次握手和四次挥手之间的那段时间可以互发多少信息。短连接的话在客户
  • tcp 连接与短连接

    千次阅读 2021-05-05 07:18:27
    连接与短连接使用TCP协议时,会在客户端服务器之间建立一条虚拟的信道,这条虚拟信道就是指连接,而建议这条连接需要3次握手,拆毁这条连接需要4次挥手,可见,我们建立这条连接是有成本的,这个成本就是效率...
  • 其编程的丰富性主要体现在通信方式报文格式的多样性上。一、通信方式主要有以下三大类:(一)SERVER/CLIENT方式1.一个Client方连接一个Server方,或称点对点(peer to peer):2.多个Client方连接一个Serv...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 130,529
精华内容 52,211
关键字:

tcp长连接和短连接

友情链接: PB12.5源码QrCoder.rar