知识大全 创建ServerSocket对象

Posted

篇首语:坚强的意志,是不会被假设所谓的命运击败的。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 创建ServerSocket对象相关的知识,希望对你有一定的参考价值。

Java网络编程从入门到精通(25):创建ServerSocket对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  ServerSocket类的构造方法有四种重载形式 它们的定义如下

   public ServerSocket() throws IOExceptionpublic ServerSocket(int port) throws IOExceptionpublic ServerSocket(int port  int backlog) throws IOExceptionpublic ServerSocket(int port  int backlog  InetAddress bindAddr) throws IOException

  在上面的构造方法中涉及到了三个参数 port backlog和bindAddr 其中port是ServerSocket对象要绑定的端口 backlog是请求队列的长度 bindAddr是ServerSocket对象要绑定的IP地址

  一 通过构造方法绑定端口

  通过构造方法绑定端口是创建ServerSocket对象最常用的方式 可以通过如下的构造方法来绑定端口

   public ServerSocket(int port) throws IOException

  如果port参数所指定的端口已经被绑定 构造方法就会抛出IOException异常 但实际上抛出的异常是BindException 从图 的异常类继承关系图可以看出 所有和网络有关的异常都是IOException类的子类 因此 为了ServerSocket构造方法还可以抛出其他的异常 就使用了IOException

  如果port的值为 系统就会随机选取一个端口号 但随机选取的端口意义不大 因为客户端在连接服务器时需要明确知道服务端程序的端口号 可以通过ServerSocket的toString方法输出和ServerSocket对象相关的信息 下面的代码输入了和ServerSocket对象相关的信息

   ServerSocket serverSocket = new ServerSocket( );System out println(serverSocket);

  运行结果

   ServerSocket[addr= / port= localport= ]

  上面的输出结果中的addr是服务端绑定的IP地址 如果未绑定IP地址 这个值是 在这种情况下 ServerSocket对象将监听服务端所有网络接口的所有IP地址 port永远是 localport是ServerSocket绑定的端口 如果port值为 (不是输出结果的port 是ServerSocket构造方法的参数port) localport是一个随机选取的端口号

  在操作系统中规定 ~ 为系统使用的端口号 端口号的最小值是 最大值是 在Windows中用户编写的程序可以绑定端口号小于 的端口 但在Linux/Unix下必须使用root登录才可以绑定小于 的端口 在前面的文章中曾使用Socket类来判断本机打开了哪些端口 其实使用ServerSocket类也可以达到同样的目的 基本原理是用ServerSocket来绑定本机的端口 如果绑定某个端口时抛出BindException异常 就说明这个端口已经打开 反之则这个端口未打开

   package server;import  *;public class ScanPort    public static void main(String[] args)            if (args length ==  )            return;        int minPort =   maxPort =  ;        String ports[] = args[ ] split( [ ] );        minPort = Integer parseInt(ports[ ]);        maxPort = (ports length >  ) ? Integer parseInt(ports[ ]) : minPort;        for (int port = minPort; port <= maxPort; port++)            try                            ServerSocket serverSocket = new ServerSocket(port);                serverSocket close();                        catch (Exception e)                            System err println(e getClass());                System err println( 端口  + port +  已经打开! );                

  在上面的代码中输出了创建ServerSocket对象时抛出的异常类的信息 ScanPort通过命令行参数将待扫描的端口号范围传入程序 参数格式为 minPort maxPort 如果只输入一个端口号 ScanPort程序只扫描这个端口号

  测试

   java server ScanPort 

  运行结果

   class  BindException端口 已经打开!class  BindException端口 已经打开!

  二 设置请求队列的长度

  在编写服务端程序时 一般会通过多线程来同时处理多个客户端请求 也就是说 使用一个线程来接收客户端请求 当接到一个请求后(得到一个Socket对象) 会创建一个新线程 将这个客户端请求交给这个新线程处理 而那个接收客户端请求的线程则继续接收客户端请求 这个过程的实现代码如下

   ServerSocket serverSocket = new ServerSocket( );   // 绑定端口// 处理其他任务的代码while(true)    Socket socket = serverSocket accept(); // 等待接收客户端请求    // 处理其他任务的代码    new ThreadClass(socket) start();   // 创建并运行处理客户端请求的线程

  上面代码中的ThreadClass类是Thread类的子类 这个类的构造方法有一个Socket类型的参数 可以通过构造方法将Socket对象传入ThreadClass对象 并在ThreadClass对象的run方法中处理客户端请求 这段代码从表面上看好象是天衣无缝 无论有多少客户端请求 只要服务器的配置足够高 就都可以处理 但仔细思考上面的代码 我们可能会发现一些问题 如果在第 行和第 行有足够复杂的代码 执行时间也比较长 这就意味着服务端程序无法及时响应客户端的请求

  假设第 行和第 行的代码是Thread sleep( ) 这将使程序延迟 秒 那么在这 秒内 程序不会执行accept方法 因此 这段程序只是将端口绑定到了 上 并未开始接收客户端请求 如果在这时一个客户端向端口 发来了一个请求 从理论上讲 客户端应该出现拒绝连接错误 但客户端却显示连接成功 究其原因 就是这节要讨论的请求队列在起作用

  在使用ServerSocket对象绑定一个端口后 操作系统就会为这个端口分配一个先进先出的队列(这个队列长度的默认值一般是 ) 这个队列用于保存未处理的客户端请求 因此叫请求队列 而ServerSocket类的accept方法负责从这个队列中读取未处理的客户端请求 如果请求队列为空 accept则处于阻塞状态 每当客户端向服务端发来一个请求 服务端会首先将这个客户端请求保存在请求队列中 然后accept再从请求队列中读取 这也可以很好地解释为什么上面的代码在还未执行到accept方法时 仍然可以接收一定数量的客户端请求 如果请求队列中的客户端请求数达到请求队列的最大容量时 服务端将无法再接收客户端请求 如果这时客户端再向服务端发请求 客户端将会抛出一个SocketException异常

  ServerSocket类有两个构造方法可以使用backlog参数重新设置请求队列的长度 在以下几种情况 仍然会采用操作系统限定的请求队列的最大长度

  ●  backlog的值小于等于

  ●  backlog的值大于操作系统限定的请求队列的最大长度

  ●  在ServerSocket构造方法中未设置backlog参数

  下面积代码演示了请求队列的一些特性 请求队列长度通过命令行参数传入SetRequestQueue

   package server;import  *;class TestRequestQueue    public static void main(String[] args) throws Exception            for (int i =  ; i <  ; i++)                    Socket socket = new Socket( localhost   );            socket getOutputStream() write( );            System out println( 已经成功创建第  + String valueOf(i +  ) +  个客户端连接! );            public class SetRequestQueue    public static void main(String[] args) throws Exception            if (args length ==  )            return;        int queueLength = Integer parseInt(args[ ]);        ServerSocket serverSocket = new ServerSocket(  queueLength);        System out println( 端口( )已经绑定 请按回车键开始处理客户端请求! );        System in read();        int n =  ;        while (true)                    System out println( <准备接收第  + (++n) +  个客户端请求! );            Socket socket = serverSocket accept();            System out println( 正在处理第  + n +  个客户端请求 );            Thread sleep( );            System out println( 第  + n +  个客户端请求已经处理完毕!> );            

  测试(按著以下步骤操作)

   执行如下命令(在执行这条命令后 先不要按回车键)

   java server SetRequestQueue 

  运行结果

  端口( )已经绑定 请按回车键开始处理客户端请求!

   执行如下命令

   java server TestRequestQueue

  运行结果

   已经成功创建第 个客户端连接!已经成功创建第 个客户端连接!Exception in thread  main   SocketException: Connection reset by peer: socket write error                       at  SocketOutputStream socketWrite (Native Method)                       at  SocketOutputStream socketWrite(SocketOutputStream java: )                       at  SocketOutputStream write(SocketOutputStream java: )                       at server TestRequestQueue main(SetRequestQueue java: )

   按回车键继续执行SetRequestQueue后 运行结果如下

   端口( )已经绑定 请按回车键开始处理客户端请求!<准备接收第 个客户端请求!正在处理第 个客户端请求第 个客户端请求已经处理完毕!><准备接收第 个客户端请求!正在处理第 个客户端请求第 个客户端请求已经处理完毕!><准备接收第 个客户端请求!

  从第二步的运行结果可以看出 当TestRequestQueue创建两个Socket连接之后 服务端的请求队列已满 并且服务端暂时无法继续执行(由于System in read()的原因而暂停程序的执行 等待用户的输入) 因此 服务端程序无法再接收客户端请求 这时TestRequestQueue抛出了一个SocketException异常 在TestRequestQueue已经创建成功的两个Socket连接已经保存在服务端的请求队列中 在这时按任意键继续执行SetRequestQueue accept方法就会从请求队列中将这两个客户端请求队列中依次读出来 从第三步的运行结果可以看出 服务端处理完这两个请求后(一个<…>包含的就是一个处理过程) 请求队列为空 这时accept处理阻塞状态 等待接收第三个客户端请求 如果这时再运行TestRequestQueue 服务端会接收几个客户端请求呢?如果将请求队列的长度设为大于 的数 TestRequestQueue的运行结果会是什么呢?读者可以自己做一下这些实验 看看和自己认为的结果是否一致

  三 绑定IP地址

  在有多个网络接口或多个IP地址的计算机上可以使用如下的构造方法将服务端绑定在某一个IP地址上

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

  bindAddr参数就是要绑定的IP地址 如果将服务端绑定到某一个IP地址上 就只有可以访问这个IP地址的客户端才能连接到服务器上 如一台机器上有两块网卡 一块网卡连接内网 另一块连接外网 如果用Java实现一个Email服务器 并且只想让内网的用户使用它 就可以使用这个构造方法将ServerSocket对象绑定到连接内网的IP地址上 这样外网就无法访问Email服务器了 可以使用如下代码来绑定IP地址

   ServerSocket serverSocket = newServerSocket(    InetAddress getByName( ));

  上面的代码将IP地址绑定到了 上 因此 服务端程序只能使用绑定了这个IP地址的网络接口进行通讯

  四 默认构造方法的使用

  除了使用ServerSocket类的构造方法绑定端口外 还可以用ServerSocket的bind方法来完成构造方法所做的工作 要想使用bind方法 必须得用ServerSocket类的默认构造方法(没有参数的构造方法)来创建ServerSocket对象 bind方法有两个重载形式 它们的定义如下

   public void bind(SocketAddress endpoint) throws IOExceptionpublic void bind(SocketAddress endpoint  int backlog) throws IOException

  bind方法不仅可以绑定端口 也可以设置请求队列的长度以及绑定IP地址 bind方法的作用是为了在建立ServerSocket对象后设置ServerSocket类的一些选项 而这些选项必须在绑定端口之前设置 一但绑定了端口后 再设置这些选项将不再起作用 下面的代码演示了bind方法的使用及如何设置ServerSocket类的选项

   ServerSocket serverSocket  = new ServerSocket();serverSocket setReuseAddress(true);serverSocket bind(new InetSocketAddress( ));ServerSocket serverSocket  = new ServerSocket();serverSocket setReuseAddress(true);serverSocket bind(new InetSocketAddress(   ));ServerSocket serverSocket  = new ServerSocket();serverSocket setReuseAddress(true);serverSocket bind(new InetSocketAddress(   )   );

  在上面的代码中设置了SO_REUSEADDR 选项(这个选项将在后面的文章中详细讨论) 如果使用下面的代码 这个选项将不起作用

   ServerSocket serverSocket  = new ServerSocket( );serverSocket setReuseAddress(true);

cha138/Article/program/Java/hx/201311/26075

相关参考

知识大全 对象的创建和存在时间

  从技术角度说OOP(面向对象程序设计)只是涉及抽象的数据类型继承以及多形性但另一些问题也可能显得非常重要本节将就这些问题进行探讨  最重要的问题之一是对象的创建及破坏方式对象需要的数据位于哪儿如何

知识大全 避免创建重复对象

  很简单的一个例子:  不要使用  Stringts=newString(hello);  这样会生成多余的对象  最好使用  Stringts=hello;  //addbychris  很多文章

知识大全 打破Java定律:无需创建对象

打破Java定律:无需创建对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  我们知道在Java

知识大全 用C#创建COM对象

用C#创建COM对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在本篇文章中我们将讨论下面的

知识大全 为 ASP.NET 创建缓存配置对象

为ASP.NET创建缓存配置对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  简介    如果

知识大全 对于使用ADO.NET通用接口创建对象

对于使用ADO.NET通用接口创建对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  使用ADO

知识大全 ASP中文显示解决技巧及创建对象方法

ASP中文显示解决技巧及创建对象方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一ASP中文显示

知识大全 Struts架构中的Session对象创建和控制

Struts架构中的Session对象创建和控制  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 获取ServerSocket信息的方法及FTP原理

Java网络编程从入门到精通(28):获取ServerSocket信息的方法及FTP原理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发

知识大全 Java对String字符串对象的创建以及管理

Java对String字符串对象的创建以及管理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  C