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

在客户/服务器通信模式中,服务器端需要创建监听特定的端口的ServerSocket,ServerSocket负责接收客户连接请求。

1、构造ServerSocket

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

public ServerSocket() throws IOException;
public ServerSocket(int port) throws IOException;
public ServerSocket(int port, int backlog) throws IOException;
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;

在以上构造方法中,参数port指定服务器要绑定的端口(即服务器要监听的端口),参数backlog指定客户连接请求队列的长度,参数bindAddr指定服务器要绑定的IP地址。

1.1、绑定端口

除了第1个不带参数的构造方法,其他构造方法都会使服务器与特定端口绑定,该端口由参数port指定。例如,以下代码创建了一个与80端口绑定的服务器:

ServerSocket serverSocket = new ServerSocket(80);

如果运行时无法绑定到80端口,以上代码就会抛出IOException,更确切地说,是抛出BindException,它是IOException的子类。BindException一般是由以下原因造成的:

  • 端口已经被其他服务器进程占用。
  • 在某些操作系统中,如果没有以超级用户的身份来运行服务器程序,那么操作系统不允许服务器绑定到1~1023之间的端口。

如果把参数port设为0,则表示由操作系统为服务器分配一个任意的可用端口,也被称为匿名端口。对于多数服务器,会使用明确的端口,而不会使用匿名端口,因为客户程序需要事先知道服务器的端口,才能方便地访问服务器。在某些场合,匿名端口有着特殊的用途。

1.2、设定客户连接请求队列的长度

当服务器进程运行时,可能会同时监听到多个客户的连接请求。例如每当一个客户进程执行以下代码:

Socket socket = new Socket("www.javathinker.net",80);

就意味着在远程www.javathinker.net主机的80端口上,监听到了一个客户的连接请求。管理客户连接请求的任务是由操作系统来完成的。操作系统把这些连接请求存储在一个先进先出的队列中。许多操作系统都限定了队列的最大长度,一般为50。当队列中的连接请求达到了队列的最大长度时,服务器进程所在的主机会拒绝新的连接请求。只有当服务器进程通过ServerSocket的accept()方法从队列中取出连接请求,使队列腾出空位,队列才能继续加入新的连接请求。

对于客户进程,如果它发出的连接请求被加入服务器的队列中,就意味着客户与服务器的连接建立成功,客户进程从Socket构造方法中正常返回。如果客户进程发出的连接请求被服务器拒绝,Socket构造方法就会抛出ConnectionException。

ServerSocket构造方法的backlog参数用来显式设置连接请求队列的长度,它将覆盖操作系统限定的队列的最大长度。值得注意的是,在以下几种情况中,仍然会采用操作系统限定的队列的最大长度:

  • backlog参数的值大于操作系统限定的队列的最大长度。
  • backlog参数的值小于或等于0。
  • 在ServerSocket构造方法中没有设置backlog参数。

下面的Client.java和Server.java用来演示服务器的连接请求队列的特性:
在这里插入图片描述
在这里插入图片描述
Client试图与Server进行100次连接。在Server类中,把连接请求队列的长度设为3。这意味着当队列中有了3个连接请求,如果Client再请求连接,就会被Server拒绝。下面按照以下步骤运行Server和Client程序:
(1)把Server类的main()方法中的“server.service();”这行程序代码注释掉。这使得服务器与8000端口绑定后,永远不会执行serverSocket.accept()方法,这意味着队列中的连接请求永远不会被取出。先运行Server程序,再运行Client程序,Client程序的打印结果如下:
在这里插入图片描述
从以上打印结果可以看出,Client与Server成功建立了3个连接后,就无法再创建其余的连接,因为服务器的队列已经满了。

(2)把Server类的main()方法按如下方式修改:
在这里插入图片描述
完成以上修改,服务器与8000端口绑定后,就会在一个while循环中不断执行serverSocket.accept()方法,该方法从队列中取出连接请求,使得队列能及时腾出空位,以容纳新的连接请求。先运行Server程序,然后运行Client程序,Client程序的打印结果如下:
在这里插入图片描述
从以上打印结果可以看出,此时Client能顺利地与Server建立100次连接。

1.3、设定绑定的IP地址

如果主机只有一个IP地址,那么在默认情况下,服务器程序就与该IP地址绑定。ServerSocket的第4个构造方法ServerSocket(int port,int backlog,InetAddress bindAddr)有一个bindAddr参数,它显式地指定服务器要绑定的IP地址,该构造方法适用于具有多个IP地址的主机。假定一个主机有两个网卡,一个网卡用于连接到Internet,IP地址为222.67.5.94,另一个网卡用于连接到本地局域网,IP地址为192.168.3.4。如果服务器仅仅被本地局域网中的客户访问,那么可以按如下方式创建ServerSocket:
在这里插入图片描述

1.4、默认构造方法的作用

ServerSocket有一个不带参数的默认构造方法。通过该方法创建的ServerSocket不与任何端口绑定,接下来还需要通过bind()方法与特定端口绑定。

这个默认构造方法的用途是,允许服务器在绑定到特定端口之前,先设置ServerSocket的一些选项。因为一旦服务器与特定端口绑定,有些选项就不能再改变了。

在以下代码中,先把ServerSocket的SO_REUSEADDR选项设为true,然后把它与8000端口绑定:
在这里插入图片描述
如果把以上程序代码改为:
在这里插入图片描述
那么serverSocket.setReuseAddress(true)方法就不起任何作用,因为SO_REUSEADDR选项必须在服务器绑定端口之前设置才有效。

2、接收和关闭与客户端的连接

ServerSocket的accept()方法从连接请求队列中取出一个客户的连接请求,然后创建与客户连接的Socket对象,并将它返回。如果队列中没有连接请求,accept()方法就会一直等待,直到接收到了连接请求才返回。

接下来,服务器从Socket对象中获得输入流和输出流,就能与客户交换数据。当服务器正在进行发送数据的操作时,如果客户端断开了连接,那么服务器端会抛出一个IOException的子类SocketException异常:
在这里插入图片描述
这只是服务器与单个客户通信中出现的异常,这种异常应该被捕获,使得服务器能继续与其他客户通信。

以下程序显示了单线程服务器采用的通信流程:
在这里插入图片描述
与单个客户通信的代码放在一个try代码块中,如果遇到异常,则该异常被catch代码块捕获。try代码块后面还有一个finally代码块,它保证不管与客户通信正常结束还是异常结束,最后都会关闭Socket,断开与这个客户的连接。

3、关闭ServerSocket

ServerSocket的close()方法使服务器释放占用的端口,并且断开与所有客户的连接。当一个服务器程序运行结束时,即使没有执行ServerSocket的close()方法,操作系统也会释放这个服务器占用的端口。因此,服务器程序并不一定要在结束之前执行ServerSocket的close()方法。

在某些情况下,如果希望及时释放服务器的端口,以便让其他程序能占用该端口,则可以显式地调用ServerSocket的close()方法。例如以下代码用于扫描1~65535之间的端口号。如果ServerSocket成功创建,则意味着该端口未被其他服务器进程绑定,否则说明该端口已经被其他进程占用:
在这里插入图片描述
以上程序代码创建了一个ServerSocket对象后,就马上关闭它,以便及时释放它占用的端口,从而避免程序临时占用系统的大多数端口。

ServerSocket的isClosed()方法判断ServerSocket是否关闭,只有执行了ServerSocket的close()方法,isClosed()方法才返回true;否则,即使ServerSocket还有没有和特定端口绑定,isClosed()方法也会返回false。

ServerSocket的isBound()方法判断ServerSocket是否已经与一个端口绑定,只要ServerSocket已经与一个端口绑定,即使它已经被关闭,isBound()方法也会返回true。

如果需要判断一个ServerSocket是否已经与特定端口绑定,并且还没有被关闭,则可以采用以下方式:
在这里插入图片描述

4、获取ServerSocket的信息

ServerSocket的以下两个get方法分别用于获得服务器绑定的IP地址,以及绑定的端口:
在这里插入图片描述

前面已经讲到,在构造ServerSocket时,如果把端口设为0,那么将由操作系统为服务器分配一个端口(称为匿名端口),程序只要调用getLocalPort()方法就能获知这个端口号。下面的RandomPort创建了一个ServerSocket,它使用的就是匿名端口:
在这里插入图片描述
多次运行RandomPort程序,可能会得到如下运行结果:
在这里插入图片描述
多数服务器会监听固定的端口,这样才便于客户程序访问服务器。匿名端口一般适用于服务器与客户之间的临时通信,通信结束后就断开连接,并且ServerSocket占用的临时端口也会被释放。

FTP就使用了匿名端口。如下图所示,FTP用于在本地文件系统与远程文件系统之间传送文件:
在这里插入图片描述
FTP使用两个并行的TCP连接:一个是控制连接,一个是数据连接。控制连接用于在客户和服务器之间发送控制信息,例如用户名和口令、改变远程目录的命令,或上传和下载文件的命令。数据连接用于传送文件。TCP服务器在21端口上监听控制连接,如果有客户要求上传或下载文件,就另外建立一个数据连接,通过它来传送文件。数据连接的建立有两种方式:
(1)如下图所示,TCP服务器在20端口上监听数据连接,TCP客户主动请求建立与该端口的连接:
在这里插入图片描述
(2)如下图所示,首先由TCP客户创建一个监听匿名端口的ServerSocket,TCP客户再把这个ServerSocket监听的端口号(调用ServerSocket的getLocalPort()方法就能得到端口号)发送给TCP服务器,然后由TCP服务器主动请求建立与客户端的连接:
在这里插入图片描述
以上第2种方式就使用了匿名端口,并且是在客户端使用的,用于和服务器建立临时的数据连接。在实际应用中,在服务器端也可以使用匿名端口。

5、ServerSocket选项

ServerSocket有以下3个选项:

  • SO_TIMEOUT:表示等待客户连接的超时时间。
  • SO_REUSEADDR:表示是否允许重用服务器所绑定的地址。
  • SO_RCVBUF:表示接收数据的缓冲区的大小。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

定义一个学生类,其中有3个私有数据成员学号、姓名、成绩,以及若于成员。 函数实现对学生数据的赋值和输出。

#include <stdio.h> // 定义学生类 typedef struct Student { int stuNum; // 学号 char name[20]; // 姓名&#xff0c;假设最长为20个字符 float score; // 成绩 } Student; // 初始化学生信息 void initializeStudent(Student *student, int num, const…

Linux--文件权限与shell外壳的理解

目录 一.Linux的用户与用户切换&#xff0c;提权 二.对文件权限的理解 1.文件权限角色的权限文件属性 2.Linux中的三种角色 3.为什么会存在所属组这个角色 4.文件属性的意义 4.1.第一个字母的意义 4.2 第2——第10个字母的意义 4.3修改文件权限的方法 三.目录权限 四…

vue-draggable-plu

一、介绍 由于 Sortablejs 的 vue3 组件一直没有更新&#xff0c;已经跟 vue3 严重脱节&#xff0c;所以诞生了这个项目&#xff0c;这个组件是基于 Sortablejs 的&#xff0c;所以如果你想了解更多关于 Sortablejs 的信息&#xff0c;可以查看Sortablejs 官网。vue-draggable…

openEuler JDK21 部署 Zookeeper 集群

zookeeper-jdk21 操作系统&#xff1a;openEuler JDK&#xff1a;21 主机名IP地址spark01192.168.171.101spark02192.168.171.102spark03192.168.171.103 安装 1. 升级内核和软件 yum -y update2. 安装常用软件 yum -y install gcc gcc-c autoconf automake cmake make \zl…

低多边形3D建模动画风格纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

Python-文件详解

一个计算机包括&#xff1a;CPU、存储器、输入设备、输出设备 存储器分为内存和硬盘 文件路径&#xff1a;一层一层文件目录组成的字符串 文件路径可以视为文件在硬盘中的身份标识&#xff0c;因为每一个文件的1路径唯一 文件之间使用/反斜杠和\正斜杠都一样 内存和硬盘的区别…

【PyTorch】模型选择、欠拟合和过拟合

文章目录 1. 理论介绍2. 实例解析2.1. 实例描述2.2. 代码实现2.2.1. 完整代码2.2.2. 输出结果 1. 理论介绍 将模型在训练数据上拟合的比在潜在分布中更接近的现象称为过拟合&#xff0c; 用于对抗过拟合的技术称为正则化。训练误差和验证误差都很严重&#xff0c; 但它们之间差…

mysql知识分享(包含安装卸载)(一)

如果博客有错误&#xff0c;请佬指正。 目录 注意&#xff1a;打开cmd时要有管理员身份打开&#xff0c;重要 为何使用数据库&#xff1f; 数据库的相关概念 关系型数据库 关系型数据库设计规则 表&#xff0c;记录&#xff0c;字段 表的关联关系 一对一关联 一对多关系 …

基于Apache DolphinScheduler构建数据平台的实践分享

很荣幸收到社区的邀请来给大家分享一下公司基于构建数据平台的实践。我将首先介绍DataLink大数据平台&#xff0c;然后讲解调度系统的升级和选型&#xff0c;最后分享我们是如何基于Apache DolphinScheduler构建数据平台的&#xff0c;以及平台的现状和未来的规划。 公司介绍 …

ReentrantLock

文章目录 相对于 synchronized 它具备如下特点&#xff1a; 可中断&#xff0c;别的线程可以打断自己&#xff0c;避免自己竞争不到锁一直block&#xff0c;发生死锁可以设置超时时间&#xff1a;tryLock&#xff0c;可以解决死锁可以设置为公平锁&#xff0c;一般不会用支持多…

Zookeeper单机模式搭建

1、下载 ​wget https://dlcdn.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz 2、解压 tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz 3、进入 apache-zookeeper-3.6.3-bin目录下&#xff0c;创建data cd apache-zookeeper-3.6.3-bin mkdir da…

JVM GUI可视化监控及诊断工具

工具既述 使用命令行工具或组合能帮您获取目标Java应用性能相关的基础信息&#xff0c;但它们存在下列局限&#xff1a; 无法获取方法级别的分析数据&#xff0c;如方法间的调用关系、各方法的调用次数和调用时间等&#xff08;这对定位应用性能瓶颈至关重要&#xff09;。要…

resnet 图像分类的项目

1. 项目文件 文件下载资源&#xff1a;resnet 图像分类的项目代码 本章利用reset34 作图像分类&#xff0c;包括计算训练集和测试集的loss、accuracy曲线&#xff0c;对训练好的网络在训练集测试集上求混淆矩阵 data 文件为训练集测试集&#xff0c;图像按照文件夹摆放inferenc…

汽车电子 -- CAN文件格式ASC

Vector提供了两种记录数据格式的格式规范&#xff1a;BLF和ASC。 先讲讲ASC。 参看&#xff1a;图文详解CAN Log文件 - ASC文件格式 一、ASC文件格式 在Vector提供的 CAN_LOG_TRIGGER_ASC_Format.pdf 提取码&#xff1a;ltjv 文件中&#xff0c;规定了CANoe/CANalyzer ASC记…

利用TCP通信实现文件传输和通信

前言 我们上一章已经熟悉了理论知识&#xff0c;这一章来练习一下 1.实现文件的传输 1.1 客户端 dir_client.c #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include …

Java ThreadLocal 实现原理 与 如何使用弱引用解决内存泄漏问题

目录 一、ThreadLocal 有什么用二、ThreadLocal 使用示例三、ThreadLocal 实现原理四、ThreadLocal 如何是使用弱引用解决内存泄漏问题4.1、强引用内存泄漏分析4.1、弱引用解决内存泄漏问题 一、ThreadLocal 有什么用 ThreadLocal 诞生于 JDK 1.2&#xff0c;用于解决多线程间的…

基于ssm学院党员管理系统论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对鄂尔多斯应用技术学院党员信息管理混乱&#xff0c;出错率高&#x…

javaWebssh图书系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

系统前景 图书有很多&#xff0c;老的图书书的管理靠纸介质&#xff0c;浪费人力和物力&#xff0c;给图书管理者带来极大的资源浪费。随着计算机信息化的普及&#xff0c;对图书的管理带来本质的改变&#xff0c;图书的销售情况以及&#xff0c;图书管理&#xff0c;以及年终对…

振弦采集仪助力岩土工程质量控制

振弦采集仪助力岩土工程质量控制 随着工程建设规模越来越大&#xff0c;建筑结构的安全性和稳定性越来越成为人们所关注的焦点。岩土工程在工程建设中占据着非常重要的地位&#xff0c;岩土工程质量控制更是至关重要。而振弦采集仪作为一种先进的检测设备&#xff0c;正得到越…

Linux命令之ps

Linux命令之ps ps命令的基本用法**常用的ps命令示例** ps命令的基本用法 ps: 显示当前终端会话中属于当前用户的进程列表。 ps -ef: 显示系统中所有进程的列表&#xff0c;包括其他用户的进程。 ps -aux: 显示详细的进程信息&#xff0c;包括CPU和内存使用情况等。 -e选项&…