Socket请求和Http请求区别和场景

news2024/12/25 12:43:27

我们在开发过程中遇到http请求和socket请求。大部分前后交互都是通过http请求的方式,那socket请求怎么使用,什么情况下使用呢?

基本概念
http请求:基于http协议的soap协议,常见的http数据请求方式有get和post,web服务。
socket请求:实现服务器与客户端之间的物理连接,并进行数据传输。主要有TCP/UDP两个协议。Socket处于网络协议的传输层。
(1)、TCP:传输控制协议,面向连接的的协议,稳定可靠。在客户端和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。
(2)、UDP:广播式数据传输,UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
在这里插入图片描述
网络传输架构层面一般分为上图的7层,http协议在TCP/IP分层模型上处于应用层,需要从上向下依次经历所有的层面发送请求,在由下向上依次传输返回请求处理后的数据。socket请求是位于传输层面,所以在向下发送请求和返回数据都要相对http请求更短。应用层面大多都是http请求,大多是用户进行业务操作发起,一般使用B/S架构。传输层面一般非用户层面的一些业务处理比较多,C/S架构相对比较合适。

socket请求的优缺点:
优点:
传输数据为字节级,传输数据可自定义,数据量小。相应的移动端开发,手机费用低;
传输数据时间短,性能高;
适合C/S之间信息实时交互;
可以加密,数据安全性高;
缺点:
需要对传输的数据进行解析,转化为应用级的数据;
对开发人员的开发水平要求高;
相对于Http协议传输,增加了开发量;

http请求的优缺点:
优点:
基于应用级的接口使用方便;
要求的开发水平不高,容错性强;
缺点:
传输速度慢,数据包大。
如实现实时交互,服务器性能压力大;
数据传输安全性差;

注意:
HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的。
tcp协议: 对应于传输层;
ip协议: 对应于网络层;
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

两者的区别:
http连接:http连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉;
socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会使连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的。

长连接
指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接。
短连接
短连接服务是每次请求都建立链接,交互完之后关闭链接
长连接与短连接的优势
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是短连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,下次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

适用场景:
Socket适用场景:网络游戏,银行交互,支付。
http适用场景:公司OA服务,互联网服务。

socket代码示例:
1、简单示例
服务端:

package socket.socket1.socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketTest {
public static void main(String[] args) {
try {
// 初始化服务端socket并且绑定9999端口
            ServerSocket serverSocket  =new ServerSocket(9999);
            //等待客户端的连接
            Socket socket = serverSocket.accept();
            //获取输入流
            BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
           //读取一行数据
           String str = bufferedReader.readLine();
            //输出打印
            System.out.println(str);
        }catch (IOException e) {
e.printStackTrace();
        }

}

}


客户端:

package socket.socket1.socket;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ClientSocket {
public static void main(String[] args) {
try {
Socket socket =new Socket("127.0.0.1",9999);
            BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String str="你好,这是我的第一个socket";
            bufferedWriter.write(str);
        }catch (IOException e) {
e.printStackTrace();
        }

}

}

启动服务端:可以看到在正常等待被连接
在这里插入图片描述
启动客户端:
在这里插入图片描述
启动客户端的同时发现服务端抛出异常
在这里插入图片描述
上诉服务断抛出异常,说明客户端请求服务端是成功的。问题的原因,首先我们需要了解。socket通信是阻塞的,他会在以下几个地方进行阻塞。第一个是accept方法,调用这个方法后,服务端一直阻塞在那里,直到有客户端连接进来。第二个是read方法,调用read方法也会进行阻塞。上诉的问题就是read方法阻塞。解决方法是客户端发送完成请求后需要bufferedWriter.flush();一下。
改进客户端请求代码:

package socket.socket1.socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ClientSocket {
public static void main(String[] args) {
try {
Socket socket =new Socket("127.0.0.1",9999);
            BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String str="你好,这是我的第一个socket";
            bufferedWriter.write(str);
            //刷新输入流
            bufferedWriter.flush();
            //关闭socket的输出流
            socket.shutdownOutput();
        }catch (IOException e) {

e.printStackTrace();

        }
}
}


此时再看服务端:可以正常接收到数据
在这里插入图片描述

由于socket通信是阻塞式的,假设我现在有A和B两个客户端同时连接到服务端上,当客户端A发送信息给服务端后,那么服务端将一直阻塞在A的客户端上(就是我们上诉说的accept阻塞),通过while循环从A客户端读取信息,此时如果B给服务端发送信息时,将进入阻塞队列,直到A客户端发送完毕,并且退出后,B才可以和服务端进行通信。简单地说,我们现在实现的功能,虽然可以让客户端不间断的和服务端进行通信,与其说是一对一的功能,因为只有当客户端A关闭后,客户端B才可以真正和服务端进行通信,这显然不是我们想要的。

2、多线程时的socket通信
上面我们说到socket的accept方法是阻塞的,我们可以通过多线程来解决
服务端:

package socket.socket1.socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {
public static void main(String[] args)throws IOException {
// 初始化服务端socket并且绑定9999端口
            ServerSocket serverSocket  =new ServerSocket(9999);
            while (true){
//等待客户端的连接
                Socket socket = serverSocket.accept();
                //每当有一个客户端连接进来后,就启动一个单独的线程进行处理
                new Thread(new Runnable() {
@Override
                    public void run() {
//获取输入流,并且指定统一的编码格式
                        BufferedReader bufferedReader =null;
                        try {
bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
                            //读取一行数据
                            String str;
                            //通过while循环不断读取信息,
                            while ((str = bufferedReader.readLine())!=null){
//输出打印
                                System.out.println("客户端说:"+str);
                            }
}catch (IOException e) {
e.printStackTrace();
                        }
}
}).start();
            }
}
}


客户端A和B代码相同如下:

package socket.socket1.socket;

import java.io.*;
import java.net.Socket;

public class ClientSocket {
public static void main(String[] args) {
try {
//初始化一个socket
            Socket socket =new Socket("127.0.0.1",9999);
            //通过socket获取字符流
            BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //通过标准输入流获取字符流
            BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
          while (true){
String str = bufferedReader.readLine();
              bufferedWriter.write(str);
              bufferedWriter.write("\n");
              bufferedWriter.flush();
          }
}catch (IOException e) {
e.printStackTrace();
        }
}
}


客户端A启动
在这里插入图片描述
客户端B启动
在这里插入图片描述
服务端可以看到数据
在这里插入图片描述
说明我们可以通过服务端多线程的方式解决accpet阻塞的问题。
服务端代码改良,使用线程池

package socket.socket1.socket;

import java.beans.Encoder;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerSocketTest {
public static void main(String[] args)throws IOException {
// 初始化服务端socket并且绑定9999端口
        ServerSocket serverSocket =new ServerSocket(9999);
        //创建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        while (true) {
//等待客户端的连接
            Socket socket = serverSocket.accept();
           Runnable runnable = () -> {
BufferedReader bufferedReader =null;
                try {
bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                    //读取一行数据
                    String str;
                    //通过while循环不断读取信息,
                    while ((str = bufferedReader.readLine()) !=null) {
//输出打印
                        System.out.println("客户端说:" + str);
                    }
}catch (IOException e) {
e.printStackTrace();
                }
};
            executorService.submit(runnable);
        }
}
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenCV实现图像的缩放几何变换,图像金字塔,高斯不同

1.前言 实现图像的放大(zoom in)和缩小(zoom out)主要通过两种途径: 几何变换。图像金字塔。 2.几何变换 通过几何变换实现图像放大和缩小功能主要是通过OpenCV的resize函数: 1 2 3 4 5 6 7 8void resi…

二.深度学习yolov5 比特家异构计算 训练与转模型01

(备份笔记 仅记录) 走国产化路上 要离开老黄的NVIDIA了,现在摸索下比特家的异构计算 yolo还停在v3的阶段 因为之前v3就已经够产品化去用了。这次也走下yolov5吧! 1.yolov5环境搭建 2.yolov5模型训练 3.yolov5模型测试 4.模型做truck 5.模型转换为…

【六袆 - Design Pattern】Strategy Pattern;策略模式;

JDK8源码使用的策略模式列举 java.util.comparator接口用于对对象进行排序。Comparator接口的compare()方法将两个对象作为参数,并返回一个整数值,表示这两个对象的相对顺序。比较器接口有许多不同的实现,每个实现都有不同的排序算法。例如&a…

OpenPCDet系列 | 5.4 PointPillars算法——AnchorHeadSingle模型预测头模块

文章目录 AnchorHeadTemplate模块1. AnchorGenerator2. ResidualCoder3. AxisAlignedTargetAssigner AnchorHeadSingle模块1. AnchorHeadSingle初始化2. AnchorHeadSingle训练前向传播3. AnchorHeadSingle测试前向传播 OpenPCDet的整个结构图: PointPillars算法属…

人人可用的开源数据可视化分析工具

大家好,我是互联网架构师! 在互联网数据大爆炸的这几年,各类数据处理、数据可视化的需求使得 GitHub 上诞生了一大批高质量的 BI 工具。 借助这些 BI 工具,我们能够大幅提升数据分析效率、生成更高质量的项目报告,让用…

UE4/5中DataTable数据表的使用

我们在UE中经常要对配置数据进行编辑,用好UE自己的DataTable自然对日常使用有所帮助。 1.蓝图使用流程 1.1 DataTable创建 使用数据表首先得创建自定义结构体,这样才好定义每一行的格式,例如这里创建如下: 然后右键选择创建Da…

LiveGBS流媒体平台GB/T28181功能-NVR硬件下级平台级联上来的通道如何过滤过滤通道类型

LiveGBS流媒体平台GB/T28181功能-NVR硬件下级平台级联上来的通道如何过滤过滤通道类型 1、上来的通道多了怎么办?2、过滤通道类型2.1、设备单独过滤2.2、全局过滤通道类型 3、过滤指定通道国标编号4、搭建GB28181视频直播平台 1、上来的通道多了怎么办? 下级平台或是NVR设备…

个人黄金投资好做吗?黄金投资交易优势体现在哪些方面

黄金的高保值性深受市场喜爱,它兼具商品和货币的双重属性。不仅实物黄金备受青睐,就连黄金投资交易也受到市场喜爱。黄金投资交易优势主要有哪些要点呢? 黄金投资交易优势一、稀有性 黄金的价值是固有的、内在的,具有千年不朽的稳…

跟庄买股票得新技巧(2023.05.16)(第二弹)

北向资金(也叫聪明的钱),它如何潜伏的(上周) 设么,你投诉大叔不写代码?好吧给你北向资金的代码 { 选股条件: 北向资金流入是昨天的两倍以上 } 百分比:REF(GPJYVALUE(6,1,1),1)>…

HttpClient5如何设置代理

文章目录 说明原始HttpClient代理HttpClient总结 说明 在这篇文章中会对HttpClient5如何进行代理进行说明,我的HttpClient版本是5.2.1。在进行代理之前请先准备好代理服务器。 原始HttpClient 下面是没有进行代理设置的代码,尝试去访问openai接口 Tes…

监控室值班人员脱岗睡岗识别算法 yolov7

监控室值班人员脱岗睡岗识别算法基于Yolov7深度学习神经网络算法,监控室值班人员脱岗睡岗识别算法模型可以7*24小时不间断自动人员是否在工位上(脱岗睡岗玩手机),若人员没有在工位,系统则立即抓拍告警,算法…

GBASE南大通用携手长亮科技 重磅推出金融数据仓库联合解决方案

随着数字化转型进程深入,金融企业对数据赋能的需求更加迫切,如何融合内外部业务数据,实现数据纵向贯通、横向穿透,让数据资源真正成为业务发展的新引擎;同时,信创浪潮风起云涌,数据库作为底层软…

深度学习语义分割篇——FCN源码解析篇

🍊作者简介:秃头小苏,致力于用最通俗的语言描述问题 🍊往期回顾:深度学习语义分割篇——FCN原理详解篇 🍊近期目标:写好专栏的每一篇文章 🍊支持小苏:点赞👍&…

分享Python采集66个菜单导航,总有一款适合您

分享Python采集66个菜单导航,总有一款适合您 Python采集的66个菜单导航下载链接:https://pan.baidu.com/s/11ElCiEa6OesmPxY6U9320w?pwdvdok 提取码:vdok jQuery手风琴滑动下拉菜单展开收缩代码 JS树形结构下拉列表菜单选择代码 简单的…

人脸识别2:InsightFace实现人脸识别Face Recognition(含源码下载)

目录 1. 前言 2. 项目安装 3. 人脸识别系统 (1)人脸检测和关键点检测 (2)人脸校准 (3)人脸特征提取 (4)人脸比对(1:1) (5)人脸搜索(1:N) &#xff08…

将数组中的“缺失值”“正无穷大”“负无穷大”替换为指定的数值np.nan_to_num()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将数组中的“缺失值”“正无穷大” “负无穷大”替换为指定的数值 np.nan_to_num() 选择题 下列说法错误的是? import numpy as np a np.array([11,-22,np.nan,np.inf,-np.inf]) print(&q…

Cefsharp113.1.40版本功能体验(支持MP3,不支持H264)-winform

下载包本地更新:NuGet Gallery | CefSharp.WinForms 113.1.40 因许可问题,不支持H264/AAC。Due to licensing issues default builds do not support proprietary codecs like H264/AAC, sites like Netflix/Twitter/Instagram/Facebook/Spotify/Apple Music wont play vide…

MS CoCo数据集

一、前言 Ms CoCo数据集是一个非常大型且常用的数据集,可以做的任务有目标检测、图像分割、图像描述等 数据集地址:链接 描述数据集的论文地址:链接 有一点需要注意:数据集的物体类别分为80类和91类两种,其中object80类…

ThingsBoard自定义万能查询节点entity query node

1、概述 大家好,我又更新干货了,还是那句话,我绝不分享那些照抄官网翻译的东西来骗订阅,我觉得那是浪费时间,要搞就搞干货,今天给大家分享ThingsBoard如何自定义规则节点,而且是万能查询节点,这是本人经过多次研究搞出来的,这个节点有什么特别之处呢?这个节点几乎可…

vue脚手架:路由的配置和使用

一、路由的配置和使用 1、引入router 在创建项目的时候可以默认用Vue脚手架中的自动生成路由文件或者自己下载(注意vue和vue-router版本的对应关系) 2、创建路由组件并引入: 在views文件夹中创建2个.vue文件作为路由组件: 引…