Java网络编程——Socket用法解析

news2024/11/25 0:35:34

在客户/服务器通信模式中,客户端需要主动创建与服务器连接的Socket,服务器端收到了客户的连接请求,也会创建与客户连接的Socket。Socket可以被看作是通信连接两端的收发器,服务器与客户都通过套接字来收发数据。

1、构造Socket

Socket的构造方法有以下几种重载形式:

    Socket();
    Socket(InetAddress address, int port) throws UnknownHostException, IOException;
    Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException;
    Socket(String host, int port)throws UnknownHostException, IOException;
    Socket(String host, int port, InetAddress localAddr, int localPort)throws IOException;;
    Socket(Proxy proxy);

除了第1个不带参数的构造方法,其他构造方法都会试图建立与服务器的连接,如果连接成功,就返回Socket对象;如果因为某些原因连接失败,就会抛出IOException。

下面的PortScanner类能够扫描主机上从1到1024之间的端口,判断这些端口是否已经被服务器程序监听。PortScanner类的scan()方法在一个for循环中创建Socket对象,每次请求连接不同的端口,如果Socket对象创建成功,就表明在当前端口有服务器程序监听。

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

/**
 * @title PortScanner
 * @description 测试
 * @author: yangyongbing
 * @date: 2023/12/5 12:03
 */
public class PortScanner {
    public static void main(String[] args) {
        String host="localhost";
        if(args.length>0){
            host=args[0];
        }
        new PortScanner().scan(host);
    }

    public void scan(String host){
        Socket socket=null;
        for(int port=1;port<1024;port++){
            try {
                socket=new Socket(host,port);
                System.out.println("There is a server on port "+port);
            }catch (IOException e){
                System.out.println("Can't connect to port "+port);
            }finally {
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

在这里插入图片描述

1.1、设定等待建立连接的超时时间

当客户端的Socket构造方法请求与服务器连接时,可能要等待一段时间。在默认情况下,Socket构造方法会一直等待下去,直到连接成功,或者出现异常。Socket构造方法请求连接时,受底层网络的传输速度的影响,可能会处于长时间的等待状态。如果希望限定等待连接的时间,那么该如何做呢?此时就需要使用第1个不带参数的构造方法。
在这里插入图片描述
以上SocketAddress类表示一个套接字的地址,它同时包含了IP地址和端口信息。以上代码用于连接到本地机器上的监听8000端口的服务器程序,等待连接的最长时间为1分钟。如果在1分钟内连接成功,则connect()方法顺利返回;如果在1分钟内出现某种异常,则抛出该异常;如果在1分钟后既没有连接成功,也没有出现异常,那么会抛出SocketTimeoutException。Socket类的connect(SocketAddress endpoint,int timeout)方法负责连接服务器,参数endpoint是指定服务器的地址,参数timeout是设定的超时时间,以ms为单位。如果参数timeout被设为0,则表示永远不会超时。

不带参数的构造方法的另一个作用是在连接服务器之前,设置Socket的选项。

1.2、设定服务器的地址

除了第1个不带参数的构造方法,其他构造方法都需要在参数中设定服务器的地址,包括服务器的IP地址或者主机名,以及端口。
在这里插入图片描述
InetAddress类表示主机的IP地址,InetAddress类提供了一系列静态工厂方法,用于构造自身的实例,例如:
在这里插入图片描述

1.3、设定客户端的地址

在一个Socket对象中,既包含远程服务器的IP地址和端口信息,也包含本地客户端的IP地址和端口信息。在默认情况下,客户端的IP地址来自客户程序所在的主机,客户端的端口则由操作系统随机分配。Socket类还有两个构造方法允许显式地设置客户端的IP地址和端口。
在这里插入图片描述

如果一个主机同时属于两个以上的网络,它就可能拥有两个以上IP地址,例如一个主机在Internet网络中的IP地址为“222.67.1.34”,在一个局域网中的IP地址为“112.5.4.3”。假定这个主机上的客户程序希望和同一个局域网上的一个服务器程序(地址为:112.5.4.45:8000)通信,客户端可按照如下方式构造Socket对象。
在这里插入图片描述

1.4、客户连接服务器时可能抛出的异常

当Socket的构造方法请求连接服务器时,可能会抛出以下异常:

  • UnknownHostException:如果无法识别主机的名字或IP地址,就会抛出这种异常。
  • ConnectException:如果没有服务器进程监听指定的端口,或者服务器进程拒绝连接,就会抛出这种异常。
  • SocketTimeoutException:如果等待连接超时,就会抛出这种异常。

以上4种异常都是IOException的直接或间接子类,如下图所示:
在这里插入图片描述
下面以ConnectTester类为例,介绍抛出各种异常的原因。ConnectTester接收用户从命令行输入的主机名和端口,然后连接到该地址,如果连接成功,就会计算建立连接所花的时间;如果连接失败,就会捕获各种异常。下面是ConnectTester类的源程序。
在这里插入图片描述
在控制台中运行命令“java ConnectTester www.javathinker.net 80”,ConnectTester类的connect()方法会请求连接Internet网上www.javathinker.net主机的80端口,如果连接成功,就会打印如下结果:
在这里插入图片描述
以上打印结果表明客户与服务器建立连接花了49ms(毫秒),在不同的主机上运行该程序,会有不同的打印结果。

1.5、使用代理服务器

在实际应用中,有的客户程序会通过代理服务器来访问远程服务器。代理服务器有许多功能,比如能作为防火墙进行安全防范,或者提高访问速度,或者具有访问特定远程服务器的权限。

以下程序代码通过代理服务器来连接远程的www.javathinker.net服务器:
在这里插入图片描述
Proxy.Type类表示代理服务器的类型,有以下可选值:

  • Proxy.Type.SOCKS:在分层的网络结构中,Type.SOCKS是位于会话层的代理类型。
  • Proxy.Type.HTTP:在分层的网络结构中,Type.HTTP是位于应用层的代理类型。
  • Proxy.Type.DIRECT:不使用代理,直接连接远程服务器。

1.6、InetAddress地址类的用法

InetAddress类表示主机的IP地址,InetAddress类的静态工厂方法getByName()用于构造自身的实例,例如:
在这里插入图片描述
InetAddress的getByName()方法的参数可以是IP地址或主机名。一般说来,主机名比IP地址要固定许多,主机名通常不会发生变化,而IP地址可能会发生变动。所以,在通过Socket连接某个服务器时,应该优先考虑提供主机名。

以下程序代码打印www.javathinker.net的地址信息:
在这里插入图片描述

InetAddress还提供了获取相应的主机名的两种方法:

  • getHostname():首先从DNS缓存中查找与IP地址匹配的主机名,如果不存在,再通过DNS服务器查找,如果找到,则返回主机名,否则返回IP地址。
  • getCanonicalHostName():通过DNS服务器查找与IP地址匹配的主机名,如果找到,则返回主机名,否则返回IP地址。

以上两种方法的区别在于,getHostname()会先查找DNS缓存,减少查找DNS服务器的概率,这样做能提高查找性能。因为查找DNS服务器是很耗时的操作。而getCanonicalHostName()总是查找DNS服务器,确保获得当前最新版本的主机名。

以下程序代码打印本地主机的主机名:
在这里插入图片描述
InetAddress类还提供了两个测试能否从本地主机连接到特定主机的方法:

public boolean isReachable(int timeout)throws IOException;
public boolean isReachable(NetworkInterface interface,int ttl,int timeout)throws IOException;

如果远程主机在参数timout(以ms为单位)指定的时间内做出回应,以上方法返回true,否则返回false。如果出现网络错误则抛出IOException。第2种方法还允许从参数指定的本地网络接口建立连接,以及TTL生存时间。TTL( Time To Live)指IP数据包被丢弃前允许存在的时间。

以下程序代码测试本地主机是否能在10s内连接www.javathinker.net网站:
在这里插入图片描述
下面介绍一个运用InetAddress类的实用范例。很多服务器会监视垃圾邮件发送者(spammer)。Spamhaus是一家国际知名反垃圾邮件机构,作为一个国际性非营利组织,提供了这一项服务。它的官方网站收集了常见的垃圾邮件发送者的IP地址的列表。例如,如何判断IP地址“108.33.56.27”是否是垃圾邮件发送者的地址呢?其步骤为调用InetAddress的getByName()方法,该方法通过DNS服务器查找“27.56.33.108.sbl.spamhaus.org”,如果查找成功(更确切地说,是返回IP地址为“127.0.0.2”的InetAddress对象),就说明这是一个垃圾邮件发送者的地址。否则,getByName()方法抛出UnknownHostException异常,就说明这不是一个垃圾邮件发送者的地址。

下面的SpamCheck类演示了如何判断特定IP地址是否为垃圾邮件发送者的IP地址。
在这里插入图片描述
通过命令“java SpamCheck 108.33.56.27 45.78.123.5154.65.93.21”运行SpamCheck类,会得到以下打印结果。
在这里插入图片描述

1.7、NetworkInterface类的用法

NetworkInterface类表示物理上的网络接口,它有两种构造自身实例的静态工厂方法,这两种方法都声明抛出SocketException。

  • getByName(String name):参数name是指定网络接口的名字。如果不存在与名字对应的网络接口,就返回null。
  • getByInetAddress(InetAddress address):参数address是指定网络接口的IP地址。如果不存在与IP地址对应的网络接口,就返回null。

以下程序代码演示如何创建NetworkInterface对象:
在这里插入图片描述
NetworkInterface类的以下方法用于获取网络接口的信息:

  • public String getName():返回网络接口的名字。
  • public Enumeration getInetAddresses():返回和网络接口绑定的所有IP地址。返回值为Enumeration类型,里面存放了表示IP地址的InetAddress对象。

2、获取Socket的信息

在一个Socket对象中,同时包含了远程服务器的IP地址和端口信息,以及客户本地的IP地址和端口信息。此外,从Socket对象中还可以获得输出流和输入流,分别用于向服务器发送数据,以及接收从服务器端发来的数据。以下方法用于获取Socket的有关信息:

  • getInetAddress():获得远程被连接进程的IP地址。
  • getPort():获得远程被连接进程的端口。
  • getLocalAddress():获得本地的IP地址。
  • getLocalPort():获得本地的端口。
  • getInputStream():获得输入流。如果Socket还没有连接,或者已经关闭,或者已经通过shutdownInput()方法关闭输入流,那么此方法会抛出IOException。
  • getOutputStream():获得输出流。如果Socket还没有连接,或者已经关闭,或者已经通过shutdownOutput()方法关闭输出流,那么此方法会抛出IOException。

下面的HTTPClient类用于访问网页www.javathinker.net/index.jsp。该网页位于一个主机名(也叫域名)为“www.javathinker.net”的远程HTTP服务器上,它监听80端口。在HTTPClient类中,先创建了一个连接到该HTTP服务器的Socket对象,然后发送符合HTTP的请求,接着接收从HTTP服务器上发回的响应结果。
在这里插入图片描述
以上HTTPClient类在发送数据时,先把字符串形式的请求信息转换为字节数组(即字符串的编码),然后发送。
在这里插入图片描述
HTTPClient类在接收数据时,把接收到的字节写到一个ByteArrayOutputStream中,它具有一个容量能够自动增长的缓冲区。如果socketIn.read(buff)方法返回“-1”,则表示读到了输入流的末尾。
在这里插入图片描述
当运行HTTPClient程序时,会打印服务器端发送的HTTP响应结果。
在这里插入图片描述
HTTP响应结果包括响应头和响应正文,中间以空行隔开。以上响应正文部分是乱码。这是因为www.javathinker.net服务器在发送正文内容时,先把它压缩成为GZIP格式,客户端需要对压缩数据进行解压,才能得到正文内容。而本范例未对压缩的正文数据解压,就直接将它打印出来,所以会显示乱码。

3、关闭Socket

当客户与服务器的通信结束时,应该及时关闭Socket,以释放Socket占用的包括端口在内的各种资源。Socket的close()方法负责关闭Socket。如果一个Socket对象被关闭,就不能再通过它的输入流和输出流进行I/O操作,否则会导致IOException。

为了确保关闭Socket的操作总是被执行,可以把这个操作放在finally代码块中:
在这里插入图片描述
Socket类提供了3个状态测试方法:

  • isClosed():如果Socket没有关闭,则返回false,否则返回true。
  • isConnected():如果Socket曾经连接到远程主机,不管当前是否已经关闭,都返回true。如果Socket从未连接到远程主机,就返回false。
  • isBound():如果Socket已经与一个本地端口绑定,则返回true,否则返回false。

如果要判断一个Socket对象当前是否处于连接状态,可采用以下方式:
在这里插入图片描述

以下这段代码演示了isClosed()和isConnected()方法在各种场景中的取值:
在这里插入图片描述
提示:Socket和ServerSocket,以及ServerSocketChannel、SocketChannel、SSLServerSocket和SSLSocket等若都实现了java.lang.Auto Closable接口。这意味着如果在try代码块中打开或创建了这些类的实例,那么即使程序没有显式地关闭它们,Java虚拟机也会在退出try代码块时自动关闭它们,释放相关的资源。另一方面,尽管这些类具有自动关闭的功能,仍然建议在程序中及时显式地关闭它们,这样可以提高程序的健壮性并提高其性能。

4、半关闭Socket

进程A与进程B通过Socket通信,假定进程A输出数据,进程B读入数据。进程A如何告诉进程B所有数据已经输出完毕呢?有几种处理办法。

(1)如果进程A与进程B交换的是字符流,并且都一行一行地读写数据,那么可以事先约定以一个特殊的标志作为结束标志,例如以字符串“bye”作为结束标志。当进程A向进程B发送一行字符串“bye”,进程B读到这一行数据后,就停止读取数据。
在这里插入图片描述
(2)进程A先发送一个消息,告诉进程B所发送的正文的长度,然后发送正文。进程B先获知进程A将发送的正文的长度,接下来只要读取该长度的字符或者字节,就停止读取数据。

(3)进程A发完所有数据后,关闭Socket。当进程B读入了进程A发送的所有数据后,再次执行输入流的read()方法时,该方法返回“-1”,如果执行BufferedReader的readLine()方法,那么该方法返回null:
在这里插入图片描述
(4)当调用Socket的close()方法关闭Socket后,它的输出流和输入流也都被关闭。有的时候,可能仅仅希望关闭输出流或输入流之一。此时可以采用Socket类提供的半关闭方法:

  • shutdownInput():关闭输入流。
  • shutdownOutput():关闭输出流。

假定进程A执行以下代码,先向进程B发送一个字符串,等到进程B接收到这个字符串后,进程A再调用Socket的shutdownOutput()方法关闭输出流。接下来进程A不允许再输出数据,但是仍可以通过输入流读入数据:
在这里插入图片描述
进程B在读入数据时,如果进程A的输出流已经关闭,进程B读入所有数据后,就会读到输入流的末尾。

值得注意的是,先后调用Socket的shutdownInput()和shutdownOutput()方法,仅仅关闭了输入流和输出流,并不等价于调用Socket的close()方法。在通信结束后,仍然要调用Socket的close()方法,因为只有该方法才会释放Socket占用的资源,比如占用的本地端口等。

Socket类还提供了两种状态测试方法,用来判断输入流和输出流是否关闭:

  • public boolean isInputShutdown():如果输入流关闭,则返回true,否则返回false。
  • public boolean isOutputShutdown():如果输出流关闭,则返回true,否则返回false。

当客户与服务器通信时,如果有一方突然结束程序,或者关闭了Socket,或者单独关闭了输入流或输出流,对另一方会造成什么影响呢?以下就用Sender类和Receiver类来演示。Sender表示发送数据的客户程序,它每隔500ms发送一行字符串,共发送20行字符串。Receiver表示接收数据的服务器程序,它每隔1s接收一行字符串,共接收20行字符串。
在这里插入图片描述

在这里插入图片描述
Sender类和Receiver类的stopWay成员变量用来指定结束通信的方式。stopWay变量的默认值为1,表示自然结束通信,此外,用户可以通过命令行参数来设置stopWay变量的值。

1.自然结束Sender和Receiver的通信

先运行“java Receiver”,再运行“java Sender”,Sender会发送20行字符串,然后自然结束运行,Receiver会接收20行字符串,然后也自然结束运行。

2.提前终止Receiver

先运行“java Receiver 2”,或者“java Receiver 3”,或者“java Receiver 4”,或者“java Receiver 5”,然后运行“java Sender”。Receiver接收了3行字符串后,就结束运行。但是Sender仍然会发送完20行字符串后,才自然结束运行。之所以会出现这种情况,是因为尽管Receiver已经结束运行,但底层的Socket并没有立即释放本地端口,操作系统探测到还有发送给该Socket的数据,会使底层Socket继续占用本地端口一段时间。

3.突然终止Sender

先运行“java Receiver”,再运行“java Sender 2”,Sender发送了3行字符串后,在没有关闭Socket的情况下,就结束运行。Receiver在第4次执行BufferedReader的readLine()方法时会抛出异常。
在这里插入图片描述

4.关闭或者半关闭Sender的Socket

先运行“java Receiver”,再运行“java Sender 3”,或者运行“java Sender 4”。Sender发送了3行字符串后,会关闭Socket(运行“java Sender 3”),或者关闭Socket的输出流(运行“java Sender 4”),然后结束运行。Receiver在第4次执行BufferedReader的readLine()方法时读到输入流的末尾,因此readLine()方法返回null。

5、设置Socket的选项

Socket的选项如下所示:

  • TCP_NODELAY:表示立即发送数据。
  • SO_RESUSEADDR:表示是否允许重用Socket所绑定的本地地址。
  • SO_TIMEOUT:表示接收数据时的等待超时时间。
  • SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket。
  • SO_SNDBUF:表示发送数据的缓冲区的大小。
  • SO_RCVBUF:表示接收数据的缓冲区的大小。
  • SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。
  • OOBINLINE:表示是否支持发送1字节的TCP紧急数据。

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

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

相关文章

企业数字化转型的七个成功案例

尽管经济形势严峻&#xff0c;但60%的企业告诉波士顿咨询公司&#xff0c;他们将在2023年增加数字化转型投资。根据Precedence Research最近的一份报告&#xff0c;到2025年&#xff0c;数字化转型市场预计将达到1.458万亿美元。 成长型股权公司PSG的董事总经理安东尼爱德华兹…

【hacker送书第10期】AI时代系列丛书(五选一)

AI时代系列丛书 AI时代程序员开发之道✨内容简介参与方式 AI时代项目经理成长之道✨内容简介参与方式 AI时代架构师修炼之道✨内容简介参与方式 AI时代产品经理升级之道✨内容简介参与方式 AI时代Python量化交易实战✨内容简介参与方式 AI时代程序员开发之道✨ 内容简介 本书是…

C#中GDI+图形图像技术(Graphics类、Pen类、Brush类)

目录 一、创建Graphics对象 1.创建Pen对象 2.创建Brush对象 &#xff08;1&#xff09;SolidBrush类 &#xff08;2&#xff09;HatchBrush类 ​​​​​​​&#xff08;3&#xff09;LinerGradientBrush类 用户界面上的窗体和控件非常有用&#xff0c;且引人注目&#…

优雅提效:Guava的字符串处理工具

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天咱们要聊一聊Google Guava这个超棒的Java库&#xff0c;尤其是它的字符串处理工具。对于Java程序员来说&#xff0c;字符串处理是日常工作的一部分&#xff0c;而Guava在这方面提供了非常强大的支持。使用Gu…

Unity中Batching优化的GPU实例化(3)

文章目录 前言一、UNITY_SETUP_INSTANCE_ID(v);二、在UnityInstancing.cginc文件中&#xff0c;看一下Unity这句话做了什么1、使用了该 .cginc 后&#xff0c;会自动预定义该函数2、需要满足GPU实例化条件&#xff0c;才会执行对应语句3、满足GPU实例化后&#xff0c;主要执行的…

Python Tornado 框架的终极指南!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python Tornado框架是一个高性能的异步Web框架&#xff0c;被广泛应用于构建实时Web应用和API服务。本文将深度解析Tornado框架&#xff0c;介绍其核心概念、异步特性、路由系统、模板引擎以及WebSocket支持等方…

通过Powershell远程控制windows服务器

1、被测服务器5985、5986端口开启&#xff0c;在网络设置中&#xff0c;点击“更改连接属性”。 2、网络配置文件中选择“专用”。 3、以管理员权限运行Powershell&#xff0c; 4.通过powershell命令在本地电脑上添加远端信任主机 winrm set winrm/config/client {TrustedHos…

世微 AP3266 大功率同步降压恒流芯片 过EMC 车灯驱动

产品描述 AP3266 是高效率、外围简单、内置功率管的同步降压恒流芯片&#xff0c;适用于4-40V输入的降压LED恒流驱动芯片。输出最大功率可达 40W&#xff0c;最大电流3.6A。AP3266 可通过调节 OVP 端口的分压电阻&#xff0c;设定输出空载电压 保护&#xff0c;避免高压 空载上…

如何搭建一套完整的智能安防视频监控平台?关于设备与软件选型的几点建议

安防视频监控系统主要由前端摄像机设备、视频显示设备、视频存储设备、安防应用软件/平台以及其它传输、辅助类设备组成。一般来说&#xff0c;安防监控系统具有可扩展和开放性&#xff0c;以方便未来的扩展和与其他系统的集成。今天我们就来介绍一下&#xff0c;搭建一套完整的…

JAVA全栈开发 MySql详解

一、数据库 1.数据储存在哪里&#xff1f; 硬盘、网盘、U盘、光盘、内存&#xff08;临时存储&#xff09; 数据持久化 使用文件来进行存储&#xff0c;数据库也是一种文件&#xff0c;像excel &#xff0c;xml 这些都可以进行数据的存储&#xff0c;但大量数据操作&#x…

搜维尔科技:Varjo XR-4 系列-专为极致沉浸感而打造!

Varjo 的新一代头显将世界上最先进的混合现实技术与顶尖的图形处理能力连接起来&#xff0c;满足最高级别的视觉保真度和沉浸感至关重要的工业用例。 光学设计的根本性突破 体验全新的沉浸感。大幅扩展的视野&#xff0c;跨越 120 x 105 度&#xff0c;打破了受人尊敬的“全双眼…

跨域的多种方案详解

浏览器的同源策略是为了保护用户的安全&#xff0c;限制了跨域请求。同源策略要求请求的域名、协议和端口必须完全一致&#xff0c;只要有一个不同就会被认为是跨域请求。 本文列举了一些处理跨域请求的解决方案&#xff1a; JSONPCORS跨域资源共享http proxynginx反向代理web…

第七次作业

1&#xff0c; 给定一个包含n1个整数的数组nums&#xff0c;其数字在1到n之间&#xff08;包含1和n)&#xff0c;可知至少存在一个重复的整数&#xff0c;假设只有一个重复的整数&#xff0c;请找出这个重复的数 arr input("") num [int(n) for n in arr.split()]…

嵌入式板级系统设计【课设】

笔记【嵌入式板级系统设计】 前言版权笔记【嵌入式板级系统设计】资料学习面包板焊接注意焊接教程 焊接电路板基础代码GPIO 外部中断 定时中断 三合一串口 综合实验 风扇控制系统下板三合一窗口综合实验 最后 前言 2023-11-20 08:49:57 以下内容源自《【创作模板五】》 仅供学…

通过K8S安装人大金仓数据库

1. 离线下载镜像&#xff0c;请点击 2. 官网下载镜像 https://www.kingbase.com.cn/xzzx/index.htm&#xff0c;根据自己的需求下载对应版本。 3. K8S需要的yaml清单 cat > kingbase.yaml << EOF apiVersion: apps/v1 kind: Deployment metadata:name: kingbase-…

将图像增广应用于Mnist数据集

将图像增广应用于Mnist数据集 不用到cifar-10的原因是要下载好久。。我就直接用在Mnist上了&#xff0c;先学会用 首先我们得了解一下图像增广的基本内容&#xff0c;这是我的一张猫图片&#xff0c;以下为先导入需要的包和展示图片 import time import torch from torch im…

javaTCP协议实现一对一聊天

我们首先要完成服务端&#xff0c;不然出错&#xff0c;运行也要先运行服务端&#xff0c;如果不先连接服务端&#xff0c;就不监听&#xff0c;那客户端不知道连接谁 服务端 import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.Actio…

超越GPT-4!谷歌发布最强多模态大模型—Gemini

12月7日凌晨&#xff0c;谷歌在官网发布了全新最强多模态大模型——Gemini。 据悉&#xff0c;Gemini有Ultra、Pro、Nano三个版本&#xff0c;可自动生成文本、代码、总结内容等&#xff0c;并能理解图片、音频和视频内容。在MMLU、DROP 、HellaSwag、GSM8K等主流评测中&#…

JVM虚拟机(已整理,已废弃)

# JVM组成 ## 简述程序计数器 线程私有&#xff0c;内部保存class字节码的行号。用于记录正在执行的字节码指令的地址。 线程私有-每个线程都有自己的程序计数器PC&#xff0c;用于记录当前线程执行哪个行号 ## 简述堆 ## 简述虚拟机栈 ## 简述堆栈区别 ## 方法内局部变量是…

【前端架构】清洁前端架构

探索前端架构&#xff1a;概述与干净的前端架构相关的一些原则&#xff08;SOLID、KISS、DRY、DDD等&#xff09;。 在我之前的一篇帖子中&#xff0c;我谈到了Signals和仍然缺少的内容[1]。现在&#xff0c;我想谈谈一个更通用的主题&#xff0c;即Clean Frontend Architectu…