Socket(一)

news2025/1/10 10:10:41

文章目录

    • 1. 简介
    • 2. 用Socket从服务器读取
    • 3. 用Socket写入服务器
    • 4. 构造和连接Socket
    • 4. 选择从哪个本地接口连接
    • 5. 构造但不连接

1. 简介

Socket允许程序员将网路连接看作是另外一个可以读/写字节的流,Socket对程序员掩盖了网络的底层细节,如错误检测、包大小、包分解、包重传、网络地址等。Socket是两台主机之间有一个连接,它可以完成7个基本操作:

  • 连接远程主机
  • 发送数据
  • 接受数据
  • 关闭端口
  • 绑定端口
  • 监听入站信息
  • 在绑定端口上接受来自远程机器的连接

Java的socket类(客户端和服务器都可以使用)提供了四个对应前面操作的方法。后面三个操作仅仅服务器需要,即等待客户端连接。这些操作有ServerSocket实现。Java程序通常采用以下方式使用客户端Socket

  • 程序用构造函数创建一个新的Socket
  • Socket尝试连接远程主机

一旦建立连接,本地和远程主机就从这个Socket得到输入流和输出流,使用这两个流相互发送数据。连接是全双工的,两台主机都可以同时发送和接受数据。数据的含义取决于协议,发送给HTTP服务器的命令就有所不同。一般会先完成某种协商握手,然后再具体传输数据。当数据传输结束后,一端或两端将关闭连接,有些协议,如HTTP1.0,要求每次请求得到服务后都要关闭连接。其他协议,如FTP和HTTP1.1 ,则允许在一个连接上处理多个请求。

2. 用Socket从服务器读取

我们用Telnet可以连接NIST(美国国家标准与技术研究院)的daytime服务器,请求当前时间。

在这里插入图片描述
60091 23-05-27 08:55:49 50 0 0 894.0 UTC(NIST) * 实际daytime的发送时间,读取这个socket的Inpustream时,就会得到这个结果。下面看看Socket是如果通过编程获取同样的内容的,首先在端口13打开time.nist.gov的连接

Socket socket=new Socket("time.nist.gov",13)

上面代码会在网络上建立连接,如果连接超时,或者由于服务器未在端口13上监听而失败,构造函数会抛出一个IOException异常,所以通常要把这个代码包装在try-catch语句块中。 使用setSoTimeout方法会为连接设置一个超时时间,超时时间按照毫秒度量。如果服务器拒绝Socket连接,那么socket要很快的抛出一个ConnectException,或者如果路由器无法确定如何将你的包发送到服务器,则要抛出一个NoRouteToHostException异常。如果一个有问题的服务器接受了连接,然后停止与你对话,但是没有主动关闭连接,对socket设置一个超时时间,这意味着对这个socket的每一个读/写都最多耗费一定的毫秒数。如果你连接的服务器挂起,会抛出一个SocketTimeoutException通知你。具体要设置多少时间这取决于你的应用的需要,以及你希望的服务器响应性。对于一个本地内部服务器来说,15s的响应时间太长了,但是对于一个负载很大的公共服务器,这个时间则很短。一旦代开socket并设置超时时间,可以调用getInpustStream来返回一个InputStream,用它从socket读取字节,一般来讲服务器可以发送任何字节。

public class QuizCardBuilder {

    public static void main(String[] args) throws IOException {
        Socket socket=null;
        try{
            socket =new Socket("time.nist.gov",13);
            socket.setSoTimeout(15000);
            InputStream in=socket.getInputStream();
            StringBuilder time=new StringBuilder();
            InputStreamReader reader=new InputStreamReader(in,"ASCII");
            for(int c=reader.read();c!=-1;c=reader.read()){
                time.append((char)c);
            }
            System.out.println(time);
        }catch (IOException ex){
            System.err.println(ex);
        }finally {
            if(socket!=null)
                try {
                    socket.close();
                }catch (IOException ex){
                    
                }
        }
    }
}

在这里插入图片描述
可以看出这和上面Telnet程序的输出是一样的

3. 用Socket写入服务器

写入服务器并不比读取服务器困难,只需要向socket请求一个输出流以及一个输入流。使用输入流在Socket发送数据时,同时还可以使用输入流读取数据,不过大多数协议都针对客户端只读取socket或者只写入socket,而不是二者同时进行,最常见的模式是,客户端发送一个请求,然后服务器响应。客户端可能发送另一个请求,服务器再做出响应。这个过程会继续,直到客户端或服务器完成工作,然后关闭连接。RFC 2229定义的dict是一个简单饿双向TCP。在这个协议中客户端向dict服务器的2628端口打开一个socket,并发送类似“DEFINE eng-lat gold”命令,这会告诉服务器使用它的英语-拉丁语字典发送单纯“gold”的定义。telnet测试结果如下:
在这里插入图片描述
下面用java代码实现:

public class QuizCardBuilder {

    public static void main(String[] args){
        Socket socket=null;
        try{
            socket =new Socket("dict.org",2628);
            socket.setSoTimeout(15000);
            OutputStream out=socket.getOutputStream();
            Writer writer=new OutputStreamWriter(out,"UTF-8");
            writer=new BufferedWriter(writer);
            InputStream in=socket.getInputStream();
            StringBuilder time=new StringBuilder();
            BufferedReader reader=new BufferedReader(new InputStreamReader(in,"UTF-8"));

            define("DEFINE english computer",writer,reader);
            writer.write("quit\r\n");
            writer.flush();
            System.out.println(time);
        }catch (IOException ex){
            System.err.println(ex);
        }finally {
            if(socket!=null)
                try {
                    socket.close();
                }catch (IOException ex){

                }
        }
    }
    static  void define(String word,Writer writer,BufferedReader bufferedReader) throws IOException {
        writer.write(word+"\r\n");
        for(String line=bufferedReader.readLine();line!=null;line=bufferedReader.readLine()){
            if(line.startsWith("250")){
                return;
            }else if(line.startsWith("552")){
                System.out.println("NOT MATCH");
                return;
            }else if(line.matches("\\d\\d\\d"))continue;
            else if(line.trim().equals("."))continue;
            else System.out.println(line);
        }

    }
}

半关闭Socket
close()方法同时关闭Socket的输入和输出。有时你希望只关闭一半连接,即输入或者输出。shutdownInput()shutdownOutput()方法只关闭连接的一半。这两个方法并不关闭Socket,实际上它们的作用是调整与Socket连接的流。使它认为已经到了流的末尾。关闭输入之后再读取会返回-1。关闭输出之后再写入Socket会抛出一个IOException异常。注意,即使半关闭了连接,或许连接的两半都关闭了,使用结束后仍然需要关闭Socket。shudown方法只会影响Socket的流,它们并不释放与Socket关联的资源,如所占用的端口等。isInputShutdown()isOutputShutdown()方法分别指出输入流和输出流是打开的还是关闭的。

4. 构造和连接Socket

java.net.Socket类是Java完成客户端TCP操作的基础类,其他建立TCP网络连接的面向客户端的类(如URL、URLConnection、Applet和JEditorpane)最终都会调用这个类的方法。这个类本身使用原生代码与主机操作系统的本地TCP栈进行通信。每个Socket构造函数指定要连接的主机和端口,主机可以指定为InetAddress或String。远程端口指定为1到65535之间的int值:

public Socket(String host,int port)throws UnknowHostException,IOException
public SOcket(InetAddress host,int port)throws IOException

下面代码查看本机已使用端口

public class QuizCardBuilder {
    public static void main(String[] args)
    {
        for(int i=1;i<256;i++)
        {
            try
            {
                InetAddress localHost=InetAddress.getLocalHost();
                Socket socket=new Socket(localHost,i);
                System.out.println("本机已经使用了端口:"+i);
            }
            catch(UnknownHostException e)
            {
                //e.printStackTrace();
            }
            catch(IOException e)
            {
                // e.printStackTrace();
            }
        }
        System.out.println("执行完毕!");
    }
}

有3个构造函数可以创建未连接的Socket。这些构造函数对于底层Socket的行为提供了更多控制,例如可以选择一个不同的代理服务器或者一个加密机制。

public Socket()
public Socket(Proxy proxy)
protected Socket(SocketImpl impl)

4. 选择从哪个本地接口连接

有两个构造函数可以指定要连接的主机和端口,以及从哪个接口和端口连接:

public Socket(String port,int port, InetAddress interface,int localPort)
public Socket(InetAddress host, int port , InetAddress interface , int localPort)

这个Socket连接到前两个参数中指定的主机和端口,它从后两个参数指定的本地网络接口和端口来连接,网络接口可以是物理接口(例如,一个以太网卡),也可以是虚拟接口(一个有多个IP地址的多宿主主机)。如果localport传入0,Java会随机选择1024到65535之间的一个可用端口。

5. 构造但不连接

目前为止所有的构造函数在创建Socket对象的同时都会打开一个远程主机的网络连接。如果没有为Socket构造函数提供任何参数,它就没有目标主机可以连接:

public Socket()

可以以后再为某个connect()方法传入一个SocketAddress来建立连接:

try{
   Socket socket=new Socket();
   SocketAddress address=new InetSocketAddress("time.nist.gov".13);
   socket.connect(adress);
  }catch(IOException ex){
    System.err.println(ex);
}

connect方法还可以传入一个参数,来指定连接超时之前等待的时间(毫秒数),默认值0表示永远等待下去

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

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

相关文章

单例模式总结

(153条消息) 解决线程安全问题&&单例模式_Master_hl的博客-CSDN博客 饿汉式 在类初始化时直接创建实例对象&#xff0c;不管你是否需要这个对象都会创建 直接实例化饿汉式&#xff08;简洁直观&#xff09; 特点&#xff1a;构造器私有化、自行创建且用静态变量保…

基于改进ISODATA算法的负荷场景曲线聚类(matlab代码)

目录 1 主要内容 聚类中心选取步骤 核方法 2 部分代码 3 程序结果 4 程序链接 1 主要内容 程序复现文献《基于机器学习的短期电力负荷预测和负荷曲线聚类研究》第三章《基于改进ISODATA算法的负荷场景曲线聚类》模型&#xff0c;该方法不止适用于负荷聚类&#xff0c;同样…

六级备考19天|CET-6|翻译练习|真题·青藏铁路|9:30~11:20

目录 1 中文 2 练习 ​ 3 答案​ 4 解析 5 订正 复习 1 中文 2 练习 3 答案 4 解析 铁路 railway/railroad 全长 with a total length of 其中xxx在海拔4000多米以上&#xff0c;非限制性定语从句&#xff0c;960 kilometers of which are over 400 me…

人工智能电话客服机器人-提升效率节约人力成本

随着科技的不断发展&#xff0c;人工智能技术已经开始广泛应用于各个领域。其中&#xff0c;人工智能电话客服机器人已经成为企业提升效率、节约人力成本的重要工具。本文将从以下几个方面探讨人工智能电话客服机器人的优势和应用。 一、人工智能电话客服机器人的优势 1.24小时…

一体化校园水电管理智能系统的实际应用

摘 要&#xff1a;针对传统的校园水电管理方法管理能力低的情况&#xff0c;提出了一种基于一体化平台的校园水电管理智能管控系统设计。通过中间件设计和显示模块设计对校园的水电情况进行采集与显示&#xff0c;设定水电用量标准&#xff0c;在水电用量超出设定标准后&#x…

开始学习使用 turtlesim, ros2, and rqt

目标&#xff1a;使用turtlesim软件包和rqt工具 Background Turtlesim是一个用于学习ROS 2的轻量级模拟器。它说明了ROS 2在最基本的层面上所做的事情&#xff0c;让我们学习知道以后你将如何处理真实的机器人或机器人模拟。 ros2工具是用户如何管理、检查和与ROS系统交互的…

涨粉秘籍 | 如何快速涨粉并转化为铁粉?

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【封装那些事】 缺失封装

缺失封装 没有将实现变化封装在抽象和层次结构中时&#xff0c;将导致这种坏味。 表现形式通常如下: 客户程序与其需要的服务变种紧密耦合&#xff0c;每当需要支持新变种或修改既有变种时&#xff0c;都将影响客户程序。每当需要在层次结构中支持新变种时&#xff0c;都添加…

港联证券投资前瞻:核电订单重回历史高位 C919圆满完成商业首航

上周五&#xff0c;沪指盘中弱势震荡下探&#xff0c;午后反弹拉升&#xff0c;科创50指数表现强势。截至收盘&#xff0c;沪指涨0.35%报3212.50点&#xff0c;深成指涨0.12%报10909.65点&#xff0c;创业板指跌0.66%报2229.27点&#xff0c;科创50指数涨1.66%&#xff1b;两市…

干货!详解playwright实现自动等待的原理

playwright在执行操作之前对元素执行一系列可操作性检查&#xff0c;以确保这些行动按预期运行。它会自动等待&#xff08;auto-wait&#xff09;所有相关检查通过&#xff0c;然后才执行请求的操作。如果所需的检查未在给定的范围内通过timeout&#xff0c;则操作将失败并显示…

vue项目中详情页向下滚动,导航选中;点击导航,详情页跳到指定区域

需求1&#xff1a;滚轮向下滚动的时候&#xff0c;导航选中 需求2&#xff1a;点击导航的时候&#xff0c;会跳转到目标区域 在生命周期中获取屏幕的高度 mounted() {//获取屏幕高度console.log(document.documentElement.clientHeight);//667}, 这里就考虑到项目优化防抖与…

2023年上半年软件设计师考试中级真题答案+解析(详细版)

目录 背景过程计算机组成原理产权保护结构化开发方法 总结 背景 2023年软考讲解 软考&#xff08;软件技术人员职业资格考试&#xff09;是中国的一项职业资格考试&#xff0c;主要针对软件行业从业人员。软考的主要目标是评估考生在软件开发、软件测试、软件项目管理等方面的…

音乐小白乐器选择,如何学一手才艺,推荐尤克里里

乐器难度说明 注意&#xff1a;这里的难度说明是音准的难度&#xff0c;就是能不能发出标准的声音 乐器按照演奏方式分类&#xff0c;分为 演奏方式乐器举例难度等级难度说明敲击木鱼&#xff0c;架子鼓&#xff0c;钢琴1敲击乐是音最准的&#xff0c;敲哪个地方就发什么音&…

MongoDB学习笔记三

目录 1.数据库增删 1.1数据库创建 1.2数据库删除 2.集合增删 2.1创建集合 2.2删除集合 3.文档增删改查 3.1查询文档 3.2创建文档 3.3删除文档 3.4更新/修改文档 1.数据库增删 1.1数据库创建 数据库创建语法格式&#xff1a; use DatabaseName 在mongodb中使用use与在m…

油猴配置教程

文章目录 目录 文章目录 前言 一. 安装油猴 二、使用步骤 三.安装插件 (ChatGPT) 四. 脚本推荐 前言 作者简介: zuiacsn 座右铭: 抱怨身处黑暗,不如提灯前行 内容介绍: 油猴 油猴&#xff08;Tampermonkey&#xff09;指的是一个流行的用户脚本管理器&#xff0c;它能使…

智能照明“暗潮涌动”

在技术持续升级、消费者观念发生转变等多方因素的共同影响下&#xff0c;与智能相关的设备销量逐渐走俏。能够为人们带来便捷、舒适的智能家居产品也逐渐走进千家万户&#xff0c;深入到人们的日常生活中。在此背景下&#xff0c;智能家居行业日渐火热&#xff0c;实现了飞速发…

SLMi331数明深力科带DESAT保护功能隔离驱动应用笔记

SLMi33X系列SLMi331数明深力科首款单通道带DESAT保护功能的IGBT/SiC隔离驱动器。内置快速去饱和(DESAT) 故障检测功能、米勒钳位功能、漏极开路故障反馈、软关断功能以及可选择的自恢复模式&#xff0c;兼容光耦隔离驱动器。 SLMi331的DESAT阈值为6.5V&#xff0c;其最大驱动电…

Facebook广告投放和海外品牌推广(KOL)哪个未来发展好一点?

在当今数字化时代&#xff0c;品牌推广和营销策略正不断演变和创新。在海外市场拓展和品牌推广方面&#xff0c;Facebook广告投放和海外品牌推广&#xff08;KOL&#xff09;已经成为两种备受关注的策略。 1.Facebook广告投放的优势&#xff1a; 广告定位精准&#xff1a;Faceb…

究诸经典,探寻大模型演变之踪迹

编者按&#xff1a;在仅仅五年的时间里&#xff0c;大语言模型、transformers几乎完全改变了自然语言处理领域。 为了便于快速、扎实、深入地学习大语言模型&#xff0c;本文整理一个简单的经典学术资料列表&#xff0c;供正在入门中的机器学习研究人员和开发者参考。 以下是译…

JAVA基础---集合

一、树结构 二叉树、二叉查找树、平衡二叉树、红黑树 1、数据结构遍历方式 1、前序遍历&#xff1a;当前节点、左子节点、右子节点 2、中序遍历&#xff1a;左子节点、当前节点、右子节点 3、后序遍历&#xff1a;左子节点、右子节点、当前节点 4、层序遍历&#xff1a;一层…