网络编程之端口----InetSocketAddress类以及通过命令查看端口冲突

 * 端口:IP地址是用来区分计算机,那么端口就是来区分计算机里的软件的。
 *   端口是一个虚拟的概念,不代表主机里真的有多个端口。端口表示的是
 *   一个16位的二进制整数,2个字节,对应十进制的0-65535,两个传输协议:
 *   TCP  UDP,同一个协议端口不能冲突。
 *   公认端口:0-1023:比如80是分配给www,21端口分配给FTP
 *   注册端口:1024-49151:分配给用户进程或应用程序
 *   动态、私有端口:49152-65535
 *   为避免冲突,端口写大些:比如8888、9999
 *通过dos命令查看端口:查看所有端口:netstat -ano
 *                查看指定端口:netstat -aon|findstr "808"
 *                查看指定进程:tasklist|findstr "808"
 *                查看具体程序:使用任务管理器查看PID
 *     可以通过以上的命令来查看端口冲突。
 *InetSocketAddress:包含端口,用于socket通信的
public class TestPort {
    public static void main(String[] args) {
        /*
        下面socketAddress和socketAddress2是一样的,本机上有配置文件,
        在C:\Windows\System32\drivers\etc下有个hosts配置文件,记事本
        打开可以看到127.0.0.1       localhost
         */
        InetSocketAddress socketAddress  =
                new InetSocketAddress("127.0.0.1",8080);
        InetSocketAddress socketAddress2  =
                new InetSocketAddress("localhost",9000);
        System.out.println(socketAddress.getHostName());
        System.out.println(socketAddress.getAddress());//地址
        System.out.println(socketAddress2.getAddress());
        System.out.println(socketAddress2.getPort());//端口
    }
}

结果:

prod.arbtr.rz.com
prod.arbtr.rz.com/127.0.0.1
localhost/127.0.0.1
9000

 

<think>我们正在解决两个问题:1.NTP服务器忽略RFC868客户端的问题2.Java网络编程中出现的Socket异常(特别是Socketclosed和端口重用问题)参考引用:[^1]:提到了TIME_WAIT状态和端口重用问题,以及SO_REUSEADDR选项的作用。[^2]:展示了使用OkHttpClient时如何配置SSLSocketFactory,但与我们当前问题关系不大。[^3]:解释了SocketException的原因,主要是由于端口处于TIME_WAIT状态导致端口耗尽。解决方案分为两部分:第一部分:NTP服务器忽略RFC868客户端根据之前提供的CMD命令方案,我们已经知道如何启用RFC868支持。但是,这里我们可能会遇到端口37被占用或者服务无法启动的问题。第二部分:Java网络编程中的SocketException主要关注两个问题:a)"Addressalreadyinuse"(端口占用)->使用SO_REUSEADDR选项b)"Socketclosed"(在已关闭的socket上操作)->确保socket状态管理下面我们分别展开。###一、解决NTP服务器忽略RFC868客户端在WindowsNTP服务器上,如果忽略RFC868客户端,通常是因为没有启用RFC868服务。RFC868使用TCP端口37。我们可以通过以下步骤启用:####1.启用RFC868服务(WindowsNTP服务器)以管理员身份运行CMD:```cmdrem启用TimeServer提供程序regadd"HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\TimeServer"/vEnabled/tREG_DWORD/d1/frem确保服务DLL正确regadd"HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Parameters"/vServiceDll/tREG_EXPAND_SZ/d"%SystemRoot%\System32\w32time.dll"/frem重启时间服务netstopw32time&&netstartw32time```####2.开放防火墙端口```cmdnetshadvfirewallfirewalladdrulename="RFC868TCP"dir=inaction=allowprotocol=TCPlocalport=37```####3.验证服务是否端口37监听```cmdnetstat-ano|findstr":37"```如果看到监听,说明RFC868服务已经启动。如果问题仍然存在,考虑切换到NTP协议(使用UDP123端口),因为RFC868已经过时。###二、解决Java网络编程中的SocketException####1."Addressalreadyinuse"(端口占用)这个问题通常发生在尝试绑定一个处于TIME_WAIT状态的端口。可以通过设置SO_REUSEADDR选项来允许立即重用端口。在Java中,可以在ServerSocket上设置:```javaServerSocketserverSocket=newServerSocket();serverSocket.setReuseAddress(true);//关键设置serverSocket.bind(newInetSocketAddress(port));```注意:必须在绑定之前设置。####2."Socketclosed"(在已关闭的socket上操作)这个异常发生在对已关闭的socket进行读写操作时。需要检查代码逻辑,确保在socket关闭后不再使用它。常见错误场景:-多线程环境下,一个线程关闭了socket,另一个线程还在使用。-在关闭socket后,仍然调用其getInputStream()或getOutputStream()。解决方法:-确保对socket的关闭操作是同步的(例如使用锁)。-在关闭socket后,将socket引用置为null,避免误用。-使用标志位来标记socket是否关闭。####3.端口耗尽问题当客户端频繁创建和关闭连接时,可能会耗尽临时端口(特别是在Windows上,临时端口范围是1024-5000)。解决方法:-增加临时端口范围(Windows):```cmdnetshintipv4setdynamicporttcpstart=10000num=50000```这将设置TCP临时端口从10000开始,共50000个。-在代码中设置SO_REUSEADDR(如上所述)允许重用处于TIME_WAIT状态的端口-调整TIME_WAIT等待时间(不推荐,因为可能影响TCP可靠性)。###三、综合解决方案示例(Java服务器避免端口占用)```javapublicclassMyServer{publicstaticvoidmain(String[]args)throwsIOException{intport=8899;ServerSocketserverSocket=newServerSocket();//设置SO_REUSEADDR以便在TIME_WAIT状态时也能绑定serverSocket.setReuseAddress(true);serverSocket.bind(newInetSocketAddress(port));while(true){Socketclient=serverSocket.accept();//处理客户端连接(使用新线程)newThread(newClientHandler(client)).start();}}staticclassClientHandlerimplementsRunnable{privateSocketclientSocket;publicClientHandler(Socketsocket){this.clientSocket=socket;}publicvoidrun(){try{//处理客户端请求//...}catch(Exceptione){e.printStackTrace();}finally{try{clientSocket.close();}catch(IOExceptione){//忽略}}}}}```###四、注意事项1.**NTP协议选择**:RFC868(TCP37)精度低且不安全,建议客户端升级到NTP(UDP123)或SNTP。2.**端口重用**:设置SO_REUSEADDR可以解决端口占用问题,但要注意安全性(允许绑定到处于TIME_WAIT状态的端口可能带来风险)。3.**资源管理**:确保及时关闭Socket,避免资源泄漏。§§相关问题§§1.如何配置Windows防火墙以允许NTP和RFC868协议?2.Java中如何设置Socket的读写超时以避免阻塞?3.如何监控Windows系统的临时端口使用情况?4.NTP服务器如何配置以支持高并发客户端?</think>### 解决NTP忽略RFC 868客户端及Java Socket异常的完整方案 #### 一、NTP服务器忽略RFC 868客户端的解决方案 **核心问题**:Windows NTP服务默认禁用RFC 868协议(TCP 37端口),导致旧客户端被拒绝[^1][^3]。 ##### 修复步骤(管理员权限): 1. **启用RFC 868服务** ```cmd reg add "HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\TimeServer" /v Enabled /t REG_DWORD /d 1 /f ``` 2. **配置防火墙开放端口** ```cmd netsh advfirewall firewall add rule name="RFC 868" dir=in action=allow protocol=TCP localport=37 ``` 3. **重启时间服务** ```cmd net stop w32time && net start w32time ``` 4. **验证服务状态** ```cmd netstat -ano | findstr ":37" # 确认TCP 37端口监听 w32tm /query /status # 检查NTP同步状态 ``` #### 二、解决Java SocketException: Socket closed/Address in use **核心问题**:端口处于`TIME_WAIT`状态导致绑定失败[^1][^3],或已关闭Socket被误操作。 ##### Java代码修复方案: ```java // 方案1:启用SO_REUSEADDR解决端口占用 ServerSocket server = new ServerSocket(); server.setReuseAddress(true); // 关键设置[^1] server.bind(new InetSocketAddress(8899)); // 方案2:安全关闭Socket防止"Socket closed" try (Socket socket = new Socket("ntp.example.com", 37)) { // 使用NTP服务 } catch (IOException e) { // 异常处理 socket.close(); // 确保关闭 } // 方案3:端口耗尽时扩大临时端口范围(Windows) Runtime.getRuntime().exec("netsh int ipv4 set dynamicport tcp start=10000 num=50000"); ``` #### 三、综合故障排查流程 ```mermaid graph TD A[客户端连接失败] --> B{错误型} B -->|Address in use| C[设置SO_REUSEADDR] B -->|Socket closed| D[检查Socket关闭逻辑] B -->|Connection refused| E[检查NTP服务状态] E --> F[验证TCP 37端口] F -->|未监听| G[启用RFC 868注册表] F -->|已监听| H[检查防火墙规则] ``` #### 四、协议兼容建议 1. **现代系统优先使用NTP协议** ```cmd w32tm /config /syncfromflags:manual /manualpeerlist:"pool.ntp.org" ``` 2. **旧设备兼容方案**: - 同时启用RFC 868和NTP - 使用协议转换中间件 - 设置双端口监听(TCP 37 + UDP 123) #### 五、预防措施 1. **Java Socket最佳实践**: ```java // 使用try-with-resources确保关闭 try (Socket socket = new Socket(); ServerSocket server = new ServerSocket()) { server.setReuseAddress(true); // ...操作代码 } ``` 2. **系统级端口管理**: ```cmd :: 增加临时端口池(Win) netsh int ipv4 set dynamicport tcp start=10000 num=50000 ``` > **关键结论**:RFC 868协议因精度低($\pm$1秒)和安全风险,应在必要最小范围内使用[^1][^3]。现代应用推荐NTP协议($\pm$0.01秒)并配合Java的`SO_REUSEADDR`选项解决端口冲突
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值