ServerSocket简单介绍

张开发
2026/6/21 23:03:28 15 分钟阅读
ServerSocket简单介绍
erverSocket.class实现了服务器套接字的功能。服务器套接字会等待通过网络传来的请求。它会根据该请求执行一些操作然后可能向请求者返回结果。ServerSocket.class的UML关系图如下所示一、构造函数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; ServerSocket(SocketImpl impl);1、int port指定服务器要绑定的端口即服务器要监听的端口,如果运行时无法绑定1~65536之间的某个端口号会抛出BindException它是IOException的子类如下所示BindException一般是由以下2种原因造成的①、端口已经被其他服务器进程占用。②、在某些操作系统中如果没有以超级用户的身份来运行服务器程序那么操作系统不允许服务器绑定到11023之间的端口。2、int backlog指定客户连接请求队列的长度如果没有指定默认值是503、InetAddress bindAddr指定服务器要绑定的IP地址二、客户连接请求队列的长度管理客户连接请求的任务是由操作系统来完成的。操作系统把这些连接请求存储在一个先进先出的队列中。许多操作系统都限定了队列的最大长度一般为50。当队列中的连接请求达到了队列的最大长度时服务器进程所在的主机会拒绝新的连接请求。只有当服务器进程通过ServerSocket的accept()函数从队列中取出连接请求使队列腾出空位队列才能继续加入新的连接请求。如下代码所示Server端package com.xxx.serverSocket; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { private ServerSocket serverSocket null; public Server() throws IOException { this.serverSocket new ServerSocket(8080,3);//端口号为8080请求连接的最大长度为3 System.out.println(服务器启动); } public void service() { while (true) { Socket socket null; try { socket serverSocket.accept(); System.out.println(New connection accepted socket.getInetAddress() socket.getPort()); } catch (IOException e) { e.printStackTrace(); } finally { if (socket ! null) { try { socket.close();//无论如何最终都会关闭这个Socket } catch (IOException e) { e.printStackTrace(); } } } } } public static void main(String[] args) throws Exception { Server server new Server(); Thread.sleep(600 * 1000); // server.service(); } }Server端运行结果如下Cient端package com.xxx.serverSocket; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { Socket[] sockets new Socket[100]; for (int i 0; i sockets.length; i) { sockets[i] new Socket(127.0.0.1, 8080); System.out.println(第 (i 1) 次连接成功); } Thread.sleep(3000); for (int i 0; i sockets.length; i) { sockets[i].close(); } } }Cient端运行结果如下如果将Server端的代码修改如下只修改了main函数中的内容调用service()函数来处理Client端的连接Socket并且在finally块中关闭Client端的连接Socketpackage com.xxx.serverSocket; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { private ServerSocket serverSocket null; public Server() throws IOException { this.serverSocket new ServerSocket(8080,3);//请求连接的最大长度为3 System.out.println(服务器启动); } public void service() { while (true) { Socket socket null; try { socket serverSocket.accept(); System.out.println(New connection accepted socket.getInetAddress() socket.getPort()); } catch (IOException e) { e.printStackTrace(); } finally { if (socket ! null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } public static void main(String[] args) throws Exception { Server server new Server(); server.service(); } }Server端运行结果如下Cient端运行结果如下三、构造函数绑定IP和bind()函数绑定port3.1、构造函数绑定IP如果主机只有一个IP地址那么在默认情况下服务器程序就与该IP地址绑定。下面这个构造函数就是绑定IP、port、和连接队列长度的构造函数public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;InetAddress bindAddr用来指定IP地址。该构造方法适用于具有多个IP地址的主机。假定一个主机有两个网卡一个网卡用于连接到InternetIP地址为222.67.5.94另一个网卡用于连接到本地局域网IP地址为192.168.3.4。如果服务器仅仅被本地局域网中的客户访问那么可以按如下方式创建ServerSocket serverSocket new ServerSocket(8080,3,InetAddress.getByName(192.168.3.4));3.2、bind()函数绑定portServerSocket有一个不带参数的默认构造方法。通过该方法创建的ServerSocket不与任何端口绑定需要通过bind()函数如下所示ServerSocket serverSocket new ServerSocket(); //需要先把SO_REUSEADDR选项设为trueSO_REUSEADDR在setReuseAddress()函数的源码里才能进行port绑定 serverSocket.setReuseAddress(true); serverSocket.bind(new InetSocketAddress(8000));//与8000端日进行绑定如果把以上程序代码改为如下所示则会失效因为SO_REUSEADDR选项必须在服务器绑定端口之前设置才有效ServerSocket serverSocket new ServerSocket(8000); serverSocket.setReuseAddress(true);四、close()函数、isBound()函数、isClosed()函数ServerSocket的close()函数使服务器释放占用的端口并且断开与所有客户的连接。当一个服务器程序运行结束时即使没有执行ServerSocket的close()函数操作系统也会释放这个服务器占用的端口。因此服务器程序并不一定要在结束之前执行ServerSocket的close()函数。在某些情况下如果希望及时释放服务器的端口以便让其他程序能占用该端口则可以显式地调用ServerSocket的close()方法。例如以下代码用于扫描165535之间的端口号。如果ServerSocket成功创建则意味着该端口未被其他服务器进程绑定否则说明该端口已经被其他进程占用如下代码所示个人认为这种方式不好不如执行shell命令再解析shell命令返回的字符串高效windows系统查看端口号的shell命令为netstat -anoServerSocket的isBound()函数判断ServerSocket是否已经与一个端口绑定只要ServerSocket已经与一个端口绑定即使它已经被关闭isBound()函数也会返回true。如果需要判断一个ServerSocket是否已经与特定端口绑定并且还没有被关闭则可以采用以下方式boolean isOpen serverSocket.isBound() !serverSocket.isClosed();五、getInetAddress()函数和getLocalPort()函数getInetAddress()函数用于获得服务器绑定的IP地址和getLocalPort()函数用于获得服务器绑定的port如果把port设为0那么将由操作系统为服务器分配一个port称为匿名port。如下代码所示package com.xxx.serverSocket; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; public class ServerSocketTest { public static void main(String[] args) throws IOException { //把port设为0请求连接的最大长度为3IP设为127.0.0.1 ServerSocket serverSocket new ServerSocket(0,3, InetAddress.getByName(127.0.0.1)); System.out.println(serverSocket.getInetAddress()); System.out.println(serverSocket.getLocalPort()); } }运行结果如下所示

更多文章