`

Java建立Socket慢的问题

阅读更多

 

在Java编程中,一般都是使用下面的语句来建立Socket

 

String ip ="192.168.0.100";

int port = 8090;

Socket socket = new Socket(ip,port);

//.......

 

 

在有些JDK和JRE的版本中,会发生这个new Socket语句非常缓慢的问题(Linux和windows环境中都可能有这种问题)。

 

我遇到这种问题,还是在Java中使用Tomcat,配置了一个数据库连接池,最小连接数配了10个,在软件一启动时,就会建立这些连接,结果就发现启动过程卡在这里了,悲剧了。。。。

 

 

更有甚者,在某个Java做得项目中,启动时,会建立一个长连接的连接池,一启动时就会建立一些Socket客户端,在启动后并发访问中来使用,结果,等啊等啊。。。

 

(最讨厌的是,不知道到底哪些版本出这样的问题,好像JDK1.5时看到过这个问题,后面的版本也有时候有问题,再有就是IBM的JDK也说不定哪个版本会出这个问题,而且,Linux平台出现问题的时候更多)

 

经过这两次,我下决心找一下这个问题,后来发现网上也有人讨论这个问题,但是很少,后来在sun(当时Java还是sun的)的bug库中有个条目在描述这个问题,链接找不到了,大体上的描述就是:

 

Java中,使用字符串的主机和整数的端口号来构造Socket的构造函数是

 

public Socket(String host, int port) throws UnknownHostException, IOException

 

可以明确的是,第一个参数的含义是host,因此,java将第一个参数字符串会理解成主机名,因此,在建立Socket时会根据主机名来查找主机的IP地址。因此,即便实际给的参数是一个字符串中包含的IP地址,但是,这是Java所无法分辨的。

 

因为机器的DNS配置不大对头,到DNS查找主机对应IP,消耗了太多的时间,所以,建立连接变得非常缓慢,就造成了前边所描述的问题。至于怎样到DNS查找,就不是本文所描述的内容了。

 

如果想通过编程避免这个问题,应该怎么处理呢?我们可以看到,Socket还可以这样建立

 

public Socket(InetAddress address, int port) throws IOException

 

而InetAddress可以通过如下的方法来创建:

 

public static InetAddress getByName(String host) throws UnknownHostException

 

 

public static InetAddress getByAddress(byte[] addr) throws UnknownHostException

 

使用字符串的host来创建InetAddress,可以想象,和使用字符串的host来创建Socket一样会缓慢(因为需要

到DNS),而是要字节数组来创建又是如何呢?我们看这个函数的解释:

 

 

在给定原始 IP 地址的情况下,返回 InetAddress 对象。参数按网络字节顺序:地址的高位字节位于 getAddress()[0] 中。

此方法不会阻塞,即不执行任何反向名称服务查找操作。

IPv4 地址 byte 数组的长度必须为 4 个字节,IPv6 byte 数组的长度必须为 16 个字节

 

首先可以明确看到,不执行反向名称服务查找查找;第二,讲IP地址转换成字节数组。因为Java看到这个函数时已经知道送来的是IP地址,所以没有查DNS的问题了。

 

从这里可以看到,其实这个问题是因为我们在送参数时,没有更加准确的去区分IP地址和主机名这两个概念。送IP地址和送主机名的场景如果清晰的区分开来就不会出这种问题了。

 

一个很糟糕的是Java的JDBC,我记得好像JDBC是建立的Socket上的,而且是字符串方式送的主机或IP地址,所以,这个问题会影响到使用数据库的Java应用,如前边提到的。

 

再有,如果打算使用字符串这种构造地址或Socket的方式,应该配置DNS,使之能够很快的找到主机。说白了,在windows下,你可以在windows\system32\drivers\etc\hosts文件这,加入一行(示例如下):

 

192.168.0.100 192.168.0.100

 

这样就告诉系统,在寻找主机名“192.168.0.100”时,从这里就返回IP地址是192.168.0.200。这样就省了很多的时间。对于Linux,是/etc/hosts文件。

 

结论:

 

(1)如果是自己建立TCP连接这类的应用,在可能的话,使用getByName这种方式,直接传IP地址;

(2)修改hosts文件,有些时候能够修改,有些情况,可能没有办法改别人系统的文件;

(3)配置好的DNS

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

16
5
分享到:
评论
20 楼 windshome 2013-03-29  
谢谢Iiwutao,一不小心写错了,向所有看帖的朋友们致歉!也希望大家发现我的错误,指给我,这也是帮我提高
19 楼 liwutao 2013-03-29  
楼主写的很好!也很用心^
不过有一点楼主笔误了吧
引用


这样就告诉系统,在寻找主机名“192.168.0.100”时,从这里就返回IP地址是192.168.0.200。这样就省了很多的时间。对于Linux,是/etc/hosts文件

windows\system32\drivers\etc\hosts这个文件里面的配置意思是前一个是IP,后一个是域名,这里返回的IP应该是192.168.0.100吧?
18 楼 hbthlw 2013-03-29  
学习就是需要有这么细致的心啊!
17 楼 windshome 2013-03-28  
liye71023326 写道
如果是自己建立TCP连接这类的应用,在可能的话,使用getByName这种方式,直接传IP地址;  按照楼主的解释,是不是应该把getByName  换成getByAddress?

getByName 参数是字符串,不知道是主机名还是IP,所以都会去找DNS啊,如果DNS配置的不好,不就慢了嘛。如果使用getByAddress,JVM知道送的是IP,就直接使用IP建立连接了,省了时间
16 楼 liye71023326 2013-03-28  
如果是自己建立TCP连接这类的应用,在可能的话,使用getByName这种方式,直接传IP地址;  按照楼主的解释,是不是应该把getByName  换成getByAddress?
15 楼 sgp420 2013-03-28  
  
14 楼 laogao3232 2013-03-27  
真没注意,感谢楼主分享。
13 楼 aotian16 2013-03-27  
多谢分享, 长知识了
12 楼 windshome 2013-03-27  
关键是你给Java的Socket送一个字符串的IP地址,它会当成主机名再解析一遍,呵呵 想想也怪怪的,JVM的确也不知道这个字符串竟然是一个IP地址而不是主机名啊!
11 楼 lipeixin 2013-03-27  
mark .
10 楼 wwwcomy 2013-03-27  
windshome 写道
我写的情况都是局域网发生的,有时候很快,但是也有时候很慢。到底为什么慢的原因,我也没有具体查找过,某些操作系统,某些Java版本。

我觉得一是从设计上和部署上避免问题,二是遇到这样的问题了能有个思路就行了。


也是 所以一般局域网都会用计算机名 然后hosts文件都会修改 也必须修改 这样应该会一定程度上减少此类问题
9 楼 darkness_t 2013-03-27  
真的长见识了~看来什么问题都怕钻研,多谢分享~
8 楼 windshome 2013-03-27  
我写的情况都是局域网发生的,有时候很快,但是也有时候很慢。到底为什么慢的原因,我也没有具体查找过,某些操作系统,某些Java版本。

我觉得一是从设计上和部署上避免问题,二是遇到这样的问题了能有个思路就行了。
7 楼 wwwcomy 2013-03-27  
很实用  不过是不是局域网内部可以不需要考虑类似问题  毕竟局域网内部寻址应该很快的吧
6 楼 windshome 2013-03-27  
很高兴能对朋友们有所帮助,十年的研发,对这类问题经历过很多,后面我会继续总结一些。因为时间少,只能在上班和带孩子之余的时间写,写的思路并不顺畅,文笔也一般,希望能越写越好吧!
5 楼 hzieept 2013-03-27  
解决了我多年困惑的一个问题
4 楼 kaiserlu 2013-03-27  
谢谢分享!很实用
3 楼 afunti 2013-03-26  
good不错哦
2 楼 baitian 2013-03-26  
谢谢,很实用
1 楼 zdb_cn 2013-03-26  
谢谢分享 !!!!  

相关推荐

    java Socket实现聊天程序

    当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象发送给服务器端 当用户发送聊天信息时,服务端将会...

    socket.io-java:socket.io-java

    没问题,socket.io-java-client 处理。 有意义的异常- 如果出现问题,SocketIO 会尝试抛出有意义的异常并提供修复提示。 状态:与 Websocket 连接已准备就绪。 XHR 处于测试阶段。 如何使用 使用 socket.io-java-...

    (超赞)JAVA精华之--深入JAVA API

    1.8 Java Socket编程 1.9 Java的内存泄漏 1.10 抽象类与接口的区别 1.11 Java变量类型间的相互转换 2 JAVA与WEB 2.1 JMX规范 2.1.1 JMX概述 2.1.2 设备层(Instrumentation Level) 2.1.3 代理层 2.1.4 分布服务层 ...

    socket服务端和客户端.zip

    用java写的socket服务端接收代码,用swift写的socket连接和接收代码,客户端建立socket套接字和服务端连接都是没有问题的

    socket编程集萃

    这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯,那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下:  服务器:  import java.io.*;  import java.net.*;  public...

    java jdk实列宝典 光盘源代码

    telnet客户端,访问系统的telnet服务实质上是与telnet服务建立socket连接,默认的telnet服务的端口是23,TelnetClient.java; UDP编程,包括收发udp报文; 聊天室服务器端,Chatserver.java;聊天室客户端,...

    java版IPMSG 含源码(在JAR包里)

    1.文件传输速度太慢,可以创建发送和接收缓存提高传输速度,最简单的办法就是加大UDP包大小,设置MyPacket.java 文件里变量packetLength = 1024*50;后速度会有很大提高.. 2.在文件传输过程中,再发消息会丢包(接收方收...

    水木清华站∶Java版精华区 含jsp及js等集合.chm

    [目录]Java简单问题 2. [目录]为什么Applet修改后在浏览器中不发生变化 3. [目录]Java中的类型转换 4. [目录]怎样找到编译时缺少的类 2. [目录]Java疑难解答 1. [目录]Java原理问题 ...

    JAVA SE学习精华集锦

    1.8 Java Socket编程 80 1.9 Java的内存泄漏 85 1.10 抽象类与接口的区别 86 1.11 Java变量类型间的相互转换 87 2 JAVA与WEB 87 2.1 JMX规范 87 2.1.1 JMX概述 87 2.1.2 设备层(Instrumentation Level) 88 2.1.3 ...

    Java聊天室程序源码(毕业设计)

    当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象发送给服务器端 当用户发送聊天信息时,服务端将会...

    cc_to_sever.zip

    java多线程socket通信、java网络编程学习心得,基本实现多线程通信,其他问题的欢饮反馈。应付作业有余了: 应用多线程实现服务器与多客户端之间的通信: ① 服务器端创建ServerSocket,循环调用accept()等待客户端...

    java flash policy.jar

    flash使用socket安全沙箱问题,需要建立安全策略服务器,java完成的一个jar,建立安全策略服务器,需要servlet-api.jar

    毕业设计基于Java的远程视频会议系统(系统+LW).rar

    因为该课题需要用到很多以前从未接触到的知识,如需要用JMF,RTP协议传输视频,JAVA socket编程,如何采集图像等知识。在用JAVA语言编码过程中,因编程规范及其他各种语法问题出现了很多错误,通过老师指导和查阅...

    JAVA多服务器通讯框架-聊天功能演示程序 V0.1 alpha

    JAVA多服务器通讯框架是基于NIO开发的Socket通讯框架,实现了客户端和服务器,服务器与服务器之间的通讯功能,适合应用于大型聊天服务器,大型游戏服务器。 本演示程序实现了一个基本的命令行聊天功能,以演示...

    Java SE实践教程 pdf格式电子书 下载(四) 更新

    6.5.2 生产者、消费者问题.. 137 6.6 小结 140 第7章 我要彩色照片——SWING的基本概念 141 7.1 讲解 142 7.1.1 Swing的基本概念 142 7.1.2 Swing组件继承关系 142 7.1.3 Swing组件一览 143 7.1.4 Swing和MVC...

    java多线程tcpsocketserver源码-Unity-UdpSocket-BitStream-Utilities:用于建立udp连接和

    虽然Unity为socket编程和多人游戏实现提供了网络api和协议,但有时你需要建立自己的裸socket和通信协议。 由于当时我没有找到一个可以使用的、清晰的、多线程的 c# 套接字在 unity 中的使用示例,因此我开始为 udp ...

    JAVA面试题最全集

    使用socket建立客户端与服务器的通信的过程 60.JAVA语言国际化应用,Locale类,Unicode 61.描述反射机制的作用 62.如何读写一个文件? 63.在图形界面中,一个按钮如何处理鼠标点击事件? 64.在图形界面中,一个...

    java网络编程技术课程设计.doc

    发送方和接收方成对的两个socket之间必须建立连接,以便在TCP协议的基础上 进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起 来,它们就可以...

    java多线程tcpsocketserver源码-UdpSocketUnity:UdpSocketUnity

    虽然Unity为socket编程和多人游戏实现提供了网络api和协议,但有时你需要建立自己的裸socket和通信协议。 由于当时我没有找到一个可以使用的、清晰的、多线程的 c# 套接字在 unity 中的使用示例,因此我开始为 udp ...

    Java聊天室程序(源代码)

    当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象发送给服务器端 当用户发送聊天信息时,服务端将会...

Global site tag (gtag.js) - Google Analytics