1、ServerSocket简单介绍
ServerSocket.class实现了服务器套接字的功能。服务器套接字会等待通过网络传来的请求。它会根据该请求执行一些操作,然后可能向请求者返回结果。ServerSocket.class的UML关系图如下所示:https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126105043372-887991768.png
一、构造函数
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的子类),如下所示:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126105139361-1931405846.png
BindException一般是由以下2种原因造成的:
①、端口已经被其他服务器进程占用。
②、在某些操作系统中,如果没有以超级用户的身份来运行服务器程序,那么操作系统不允许服务器绑定到1~1023之间的端口。
2、int backlog指定客户连接请求队列的长度,如果没有指定,默认值是50;
3、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端运行结果如下:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126105557093-1857568249.png
[*]Cient端
package com.xxx.serverSocket;import java.net.Socket;public class Client { public static void main(String[] args) throws Exception { Socket[] sockets = new Socket; for (int i = 0; i < sockets.length; i++) { sockets = new Socket("127.0.0.1", 8080); System.out.println("第" + (i + 1) + "次连接成功"); } Thread.sleep(3000); for (int i = 0; i < sockets.length; i++) { sockets.close(); } }}Cient端运行结果如下:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126105632614-2121452734.png
如果将Server端的代码修改如下(只修改了main函数中的内容,调用service()函数来处理Client端的连接Socket,并且在finally块中关闭Client端的连接Socket):
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);//请求连接的最大长度为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端运行结果如下:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126110750626-549626388.png
Cient端运行结果如下:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126110818848-1170985684.png
三、构造函数绑定IP和bind()函数绑定port
3.1、构造函数绑定IP
如果主机只有一个IP地址,那么在默认情况下,服务器程序就与该IP地址绑定。下面这个构造函数就是绑定IP、port、和连接队列长度的构造函数:
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;InetAddress bindAddr用来指定IP地址。该构造方法适用于具有多个IP地址的主机。假定一个主机有两个网卡,一个网卡用于连接到Internet,IP地址为222.67.5.94,另一个网卡用于连接到本地局域网,IP地址为192.168.3.4。如果服务器仅仅被本地局域网中的客户访问,那么可以按如下方式创建
ServerSocket serverSocket = new ServerSocket(8080,3,InetAddress.getByName("192.168.3.4"));3.2、bind()函数绑定port
ServerSocket有一个不带参数的默认构造方法。通过该方法创建的ServerSocket不与任何端口绑定,需要通过bind()函数,如下所示:
ServerSocket serverSocket = new ServerSocket();//需要先把SO_REUSEADDR选项设为true(SO_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()方法。例如以下代码用于扫描1~65535之间的端口号。如果ServerSocket成功创建,则意味着该端口未被其他服务器进程绑定,否则说明该端口已经被其他进程占用,如下代码所示(个人认为这种方式不好,不如执行shell命令再解析shell命令返回的字符串高效,windows系统查看端口号的shell命令为netstat -ano):
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126111400473-384683648.png
ServerSocket的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,请求连接的最大长度为3,IP设为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()); }}运行结果如下所示:
https://img2024.cnblogs.com/blog/2485827/202601/2485827-20260126111548996-484687767.png
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 分享、互助 让互联网精神温暖你我 感谢,下载保存了 懂技术并乐意极积无私分享的人越来越少。珍惜 不错,里面软件多更新就更好了 新版吗?好像是停更了吧。 这个有用。 喜欢鼓捣这些软件,现在用得少,谢谢分享! 鼓励转贴优秀软件安全工具和文档! 新版吗?好像是停更了吧。 感谢分享 感谢,下载保存了 不错,里面软件多更新就更好了 这个有用。 热心回复! 分享、互助 让互联网精神温暖你我 感谢发布原创作品,程序园因你更精彩 感谢分享,学习下。 不错,里面软件多更新就更好了 鼓励转贴优秀软件安全工具和文档!
页:
[1]
2