导航:首页 > 编程语言 > java网络编程精解源代码

java网络编程精解源代码

发布时间:2023-06-08 18:06:32

java经典教材

随着JAVA行业日益的发展,高薪资也吸引到各行各业的从业者。下面就推荐几本JAVA经典教材供大家参考:
1. 《Java经典实例》收集了Java开发人员经常遇到的成百个问题的解决方案,涵盖了Java应用的方方面面,堪称讲述Java应用的网络全书。
2. 《Java 实时编程》主要讲述使用Java RTS进行Java实时编程的各类主题。主要内容包括3个部分:第一部分"实时计算概念",明确定义计算领域中的实时概念,并讨论了许多实时应用程序设计和开发的理论;第二部分"高级Java RTS",提供充足的示例代码来说明Java RTS的内部运作机制及其使用;第三部分"使用Java RTS",讨论了实际的案例研究。
3. 《Java网络编程精解》,通过这本书读者不仅可以掌握网络编程的实用技术,还可以进一步提高按照面向对象的思想来设计和编写Java软件的能力。

② java socket网络编程

//==============Server.java=================//
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(12345);
System.out.println("服务器就绪,请启动客户端.");
Socket so = s.accept();
byte[] buff = new byte[1024];
int read = so.getInputStream().read(buff);
String[] abc=new String(buff,0,read).split("\\D+");
int a = Integer.parseInt(abc[0]);
int b = Integer.parseInt(abc[1]);
int c = Integer.parseInt(abc[2]);
if(!cbt(a,b,c))
so.getOutputStream().write("输入的数据无法组成三角形.".getBytes());
else
so.getOutputStream().write(getArea(a,b,c).getBytes());
so.getOutputStream().flush();
so.close();
s.close();
}

private static String getArea(int a, int b, int c) {
float s = (a+b+c)/2f;
return "面积: "+Math.sqrt(s*(s-a)*(s-b)*(s-c));
}

private static boolean cbt(int a, int b, int c) {
return a>0&&b>0&&c>0&&a+b>c&&b+c>a&&a+c>b;
}
}

//=================Client.java======================//
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("输入三角形的三边并用逗号隔开,如: (3,4,5) ");
byte[] buff=new byte[64];
int r = System.in.read(buff);
String ipaddr = "localhost";//根据情况改变,在本机调试就不改了
Socket so = new Socket(ipaddr,12345);
so.getOutputStream().write(new String(buff,0,r).getBytes());
r = so.getInputStream().read(buff);
so.close();
String rs = new String(buff,0,r);
System.out.println(rs);
}

}

//先启动Server,再启动Client

③ Java网络编程从入门到精通(4):DNS缓存

在通过DNS查找域名的过程中 可能会经过多台中间DNS服务器才能找到指定的域名 因此 在DNS服务器上查找域名是非常昂贵的操作 在Java中为了缓解这个问题 提供了DNS缓存 当InetAddress类第一次使用某个域名(如)创建InetAddress对象后 JVM就会将这个域名和它从DNS上获得的信息(如IP地址)都保存在DNS缓存中 当下一次InetAddress类再使用这个域名时 就直接从DNS缓存里获得所需的信息 而无需再访问DNS服务器

DNS缓存在默认时将永远保留曾经访问过的域名信息 但我们可以修改这个默认值 一般有两种方法可以修改这个默认值

在程序中通过java security Security setProperty方法设置安全属性nel的值(单位 秒) 如下面的代码将缓存超时设为 秒

java security Security setProperty( nel );

设置java security文件中的neorkaddresl属性 假设JDK的安装目录是C jdk 那么java security文件位于c jdk jrelibsecurity目录中 打开这个文件 找到nel属性 并将这个属性值设为相应的缓存超时(单位 秒)

如果将nel属性值设为 那么DNS缓存数据将永远不会释放 下面的代码演示了使用和不使用DNS缓存所产生效果

package mynet;import *;publicclass MyDNS{publicstaticvoidmain(String[]args)throwsException{//args[ ]:本机名args[ ] 缓冲时间if(args length< )return;java security Security setProperty( nel args[ ]);longtime=System currentTimeMillis();InetAddressaddresses []=InetAddress getAllByName(args[ ]);System out println( addresses : +String valueOf(System currentTimeMillis() time)+ 毫秒 );for(InetAddressaddress:addresses )System out println(address);System out print( 按任意键继续 );System in read();time=System currentTimeMillis();InetAddressaddresses []=InetAddress getAllByName(args[ ]);System out println( addresses : +String valueOf(System currentTimeMillis() time)+ 毫秒 );for(InetAddressaddress:addresses )System out println(address);}}

在上面的代码中设置了DNS缓存超时(通过args[ ]参数) 用户可以通过命令行参数将这个值传入MyDNS中 这个程序首先使用getAllByName建立一个InetAddress数组 然后通过System in read使程序暂停 当用户等待一段时间后 可以按任意键继续 并使用同一个域名(args[ ])再建立一个InetAddress数组 如果用户等待的这段时间比DNS缓存超时小 那么无论情况如何变化 addresses 和addresses 数组中的元素是一样的 并且创建addresses 数组所花费的时间一般为 毫秒(小于 毫秒后 Java无法获得更精确的时间)

测试

执行如下命令(将DNS缓存超时设为 秒)

java mynet MyDNS

运行结果 (在 秒之内按任意键)

addresses : 毫秒/ 按任意键继续addresses : 毫秒/

运行结果 (在 秒后按任意键)

addresses : 毫秒/ 按任意键继续addresses : 毫秒/

在上面的测试中可能出现两个运行结果 如果在出现 按任意键继续… 后 在 秒之内按任意键继续后 就会得到运行结果 从这个结果可以看出 addresses 所用的时间为 毫秒 也就是说 addresses 并未真正访问DNS服务器 而是直接从内存中的DNS缓存得到的数据 当在 秒后按任意键继续后 就会得到运行结果 这时 内存中的DNS缓存中的数据已经释放 所以addresses 还得再访问DNS服务器 因此 addresses 的时间是 毫秒(addresses 和addresses 后面的毫秒数可能在不同的环境下的值不一样 但一般情况下 运行结果 的addresses 的值为 或是一个接近 的数 如 运行结果 的addresses 的值一般会和addresses 的值很接近 或是一个远比 大的数 如 )

测试

执行如下命令(ComputerName为本机的计算机名 DNS缓存超时设为永不过期[ ])

java mynet MyDNS ComputerName

运行结果(按任意键继续之前 将 删除)

addresses : 毫秒myuniverse/ myuniverse/ 按任意键继续addresses : 毫秒myuniverse/ myuniverse/

从上面的测试可以看出 将DNS缓存设为永不过期后 无论过多少时间 按任意键后 addresses 任然得到了两个IP地址( 和 ) 而且addresses 的时间是 毫秒 但在这时 已经被删除 因此可以判断 addresses 是从DNS缓存中得到的数据 如果运行如下的命令 并在 秒后按任意键继续后 addresses 就会只剩下一个IP地址( )

java mynet MyDNS ComputerName

如果域名在DNS服务器上不存在 那么客户端在进行一段时间的尝试后(平均为 秒) 就会抛出一个UnknownHostException异常 为了让下一次访问这个域名时不再等待 DNS缓存将这个错误信息也保存了起来 也就是说 只有第一次访问错误域名时才进行 称左右的尝试 以后再访问这个域名时将直接抛出UnknownHostException异常 而无需再等待 秒钟

访问域名失败的原因可能是这个域名真的不存在 也可能是因为DNS服务器或是其他的硬件或软件的临时故障 因此 一般不能将这个域名错误信息一直保留 在Java中可以通过neorkaddresl属性设置保留这些信息的时间 这个属性的默认值是 秒 它也可以通过java security Security setProperty方法或java security文件来设置 下面的代码演示了neorkaddresl属性的用法

package mynet;import *;publicclass MyDNS {publicstaticvoidmain(String[]args)throwsException{java security Security setProperty( neorkaddresl );longtime= ;try{time=System currentTimeMillis();InetAddress getByName( );}catch(Exceptione){System out println( 不存在!address : +String valueOf(System currentTimeMillis() time)+ 毫秒 );}//Thread sleep( );//延迟 秒try{time=System currentTimeMillis();InetAddress getByName( );}catch(Exceptione){System out println( 不存在!address : +String valueOf(System currentTimeMillis() time)+ 毫秒 );}}}

在上面的代码中将neorkaddresl属性值设为 秒 这个程序分别测试了address 和address 访问(这是个不存在的域名 读者可以将其换成任何不存在的域名)后 用了多长时间抛出UnknownHostException异常

运行结果

不存在!address : 毫秒不存在!address : 毫秒

我们从上面的运行结果可以看出 address 使用了 毫秒就抛出了异常 因此 可以断定address 是从DNS缓存里获得了域名不可访问的信息 所以就直接抛出了UnknowHostException异常 如果将上面代码中的延迟代码的注释去掉 那么可能得到如下的运行结果

不存在!address : 毫秒不存在!address : 毫秒

从上面的运行结果可以看出 在第 秒时 DNS缓存中的数据已经被释放 因此 address 仍需要访问DNS服务器才能知道是不可访问的域名

在使用DNS缓存时有两点需要注意

可以根据实际情况来设置nel属性的值 一般将这个属性的值设为 但如果访问的是动态映射的域名(如使用动态域名服务将域名映射成ADSL的动态IP) 就可能产生IP地址变化后 客户端得到的还是原来的IP地址的情况

lishixin/Article/program/Java/hx/201311/11147

④ GitHub上面有哪些经典的java框架源码

⑤ Java网络编程从入门到精通(33):非阻塞I/O的缓冲区(Buffer)

如果将同步I/O方式下的数据传输比做数据传输的零星方式(这里的零星是指在数据传输的过程中是以零星的字节方式进行的) 那么就可以将非阻塞I/O方式下的数据传输比做数据传输的集装箱方式(在字节和低层数据传输之间 多了一层缓冲区 因此 可以将缓冲区看做是装载字节的集装箱) 大家可以想象 如果我们要运送比较少的货物 用集装箱好象有点不太合算 而如果要运送上百吨的货物 用集装箱来运送的成本会更低 在数据传输过程中也是一样 如果数据量很小时 使用同步I/O方式会更适合 如果数据量很大时(一般以G为单位) 使用非阻塞I/O方式的效率会更高 因此 从理论上说 数据量越大 使用非阻塞I/O方式的单位成本就会越低 产生这种结果的原因和缓冲区的一些特性有着直接的关系 在本节中 将对缓冲区的一些主要特性进行讲解 使读者可以充分理解缓冲区的概念冲森 并能通过缓冲区来提高程序的执行效率

创建缓冲区

Java提供了七个基本的缓冲区 分别由七个类来扰判拍管理 它们都可以在java nio包中找到 这七个类如下所示

ByteBuffer

ShortBuffer

IntBuffer

CharBuffer

FloatBuffer

DoubleBuffer

LongBuffer

这七个类中的方法类似 只是它们的返回值或参数和相应的简单类型相对应 如ByteBuffer类的get方法返回了byte类型的数据 而put方法需要一个byte类型的参数 在CharBuffer类中的get和put方法返回和传递的数据类型就是char 这七个类都没有public构造方法 因此 它们不能通过new来创建相应的对象实例 这些类都可以通过两种方式来创建相应的对象实例

通过静态方法allocate来创建缓冲区

这七类都有一个静态的allocate方法 通过这个方法可以创建有最大容量限制的缓冲区对象 allocate的定义如下

ByteBuffer类中的allocate方法

(intcapacity)

IntBuffer类中的allocate方法

publicstaticIntBufferallocate(intcapacity)

其他五个缓冲区类中的allocate 方法定义和上面的定义类似 只是返回值的类型是相应的缓冲区缓羡类

allocate方法有一个参数capacity 用来指定缓冲区容量的最大值 capacity的不能小于 否则会抛出一个IllegalArgumentException异常 使用allocate来创建缓冲区 并不是一下子就分配给缓冲区capacity大小的空间 而是根据缓冲区中存储数据的情况来动态分配缓冲区的大小(实际上 在低层Java采用了数据结构中的堆来管理缓冲区的大小) 因此 这个capacity可以是一个很大的值 如 * ( M) allocate的使用方法如下

ByteBufferbyteBuffer=ByteBuffer allocate( );IntBufferintBuffer=IntBuffer allocate( );

在使用allocate创建缓冲区时应用注意 capacity的含义随着缓冲区的不同而不同 如创建字节缓冲区时 capacity指的是字节数 而在创建整型(int)缓冲区时 capacity指的是int型值的数目 如果转换成字数 capacity的值应该乘 如上面代码中的intBuffer缓冲区最大可容纳的字节数是 * = 个

通过静态方法wrap来创建缓冲区

使用allocate方法可以创建一个空的缓冲区 而wrap方法可以利用已经存在的数据来创建缓冲区 wrap方法可以将数组直接转换成相应类型的缓冲区 wrap方法有两种重载形式 它们的定义如下

ByteBuffer类中的wrap方法

publicstaticByteBufferwrap(byte[]array)publicstaticByteBufferwrap(byte[]array intoffset intlength)

IntBuffer类中的wrap方法

publicstaticIntBufferwrap(byte[]array)publicstaticIntBufferwrap(byte[]array intoffset intlength)

其他五个缓冲区类中的wrap 方法定义和上面的定义类似 只是返回值的类型是相应的缓冲区类

在wrap方法中的array参数是要转换的数组(如果是其他的缓冲区类 数组的类型就是相应的简单类型 如IntBuffer类中的wrap方法的array就是int[]类型) offset是要转换的子数组的偏移量 也就是子数组在array中的开始索引 length是要转换的子数组的长度 利用后两个参数可以将array数组中的一部分转换成缓冲区对象 它们的使用方法如下

byte[]myByte=newbyte[]{ };int[]myInt=newint[]{ };ByteBufferbyteBuffer=ByteBuffer wrap(myByte);IntBufferintBuffer=IntBuffer wrap(myInt );

可以通过缓冲区类的capacity方法来得到缓冲区的大小 capacity方法的定义如下

publicfinalintcapacity()

如果使用allocate方法来创建缓冲区 capacity方法的返回值就是capacity参数的值 而使用wrap方法来创建缓冲区 capacity方法的返回值是array数组的长度 但要注意 使用wrap来转换array的字数组时 capacity的长度仍然是原数组的长度 如上面代码中的intBuffer缓冲区的capacity值是 而不是

除了可以将数组转换成缓冲区外 也可以通过缓冲区类的array方法将缓冲区转换成相应类型的数组 IntBuffer类的array方法的定义方法如下(其他缓冲区类的array的定义类似)

publicfinalint[]array()

下面的代码演示了如何使用array方法将缓冲区转换成相应类型的数组

int[]myInt=newint[]{ };IntBufferintBuffer=IntBuffer wrap(myInt );for(intv:intBuffer array()) System out print(v+ );

在执行上面代码后 我们发现输出的结果是 而不是 这说明在将子数组转换成缓冲区的过程中实际上是将整个数组转换成了缓冲区 这就是用wrap包装子数组后 capacity的值仍然是原数组长度的真正原因 在使用array方法时应注意 在以下两种缓冲区中不能使用array方法

只读的缓冲区如果使用只读缓冲区的array方法 将会抛出一个ReadOnlyBufferException异常

使用allocateDirect方法创建的缓冲区

如果调用这种缓冲区中的array方法 将会抛出一个UnsupportedOperationException异常

可以通过缓冲区类的hasArray方法来判断这个缓冲区是否可以使用array方法 如果返回true 则说明这个缓冲区可以使用array方法 否则 使用array方法将会抛出上述的两种异常之一

注意 使用array方法返回的数组并不是缓冲区数据的副本 被返回的数组实际上就是缓冲区中的数据 也就是说 array方法只返回了缓冲区数据的引用 当数组中的数据被修改后 缓冲区中的数据也会被修改 返之也是如此 关于这方面内容将在下一节 读写缓冲区中的数据 中详细讲解

在上述的七个缓冲区类中 ByteBuffer类和CharBuffer类各自还有另外一种方法来创建缓冲区对象

ByteBuffer类

可以通过ByteBuffer类的allocateDirect方法来创建ByteBuffer对象 allocateDirect方法的定义如下

Direct(intcapacity)

使用allocateDirect方法可以一次性分配capacity大小的连续字节空间 通过allocateDirect方法来创建具有连续空间的ByteBuffer对象虽然可以在一定程度上提高效率 但这种方式并不是平台独立的 也就是说 在一些操作系统平台上使用allocateDirect方法来创建ByteBuffer对象会使效率大幅度提高 而在另一些操作系统平台上 性能会表现得非常差 而且allocateDirect方法需要较长的时间来分配内存空间 在释放空间时也较慢 因此 在使用allocateDirect方法时应谨慎

通过isDirect方法可以判断缓冲区对象(其他的缓冲区类也有isDirect方法 因为 ByteBuffer对象可以转换成其他的缓冲区对象 这部分内容将在后面讲解)是用哪种方式创建的 如果isDirect方法返回true 则这个缓冲区对象是用allocateDirect方法创建的 否则 就是用其他方法创建的缓冲区对象

CharBuffer类

我们可以发现 上述的七种缓冲区中并没有字符串缓冲区 而字符串在程序中却是最常用的一种数据类型 不过不要担心 虽然java nio包中并未提供字符串缓冲区 但却可以将字符串转换成字符缓冲区(就是CharBuffer对象) 在CharBuffer类中的wrap方法除了上述的两种重载形式外 又多了两种重载形式 它们的定义如下

publicstaticCharBufferwrap(CharSequencecsq)publicstaticCharBufferwrap(CharSequencecsq intstart intend)

其中csq参数表示要转换的字符串 但我们注意到csq的类型并不是String 而是CharSequence CharSequence类Java中四个可以表示字符串的类的父类 这四个类是String StringBuffer StringBuilder和CharBuffer(大家要注意 StringBuffer和本节讲的缓冲区类一点关系都没有 这个类在java lang包中) 也就是说 CharBuffer类的wrap方法可以将这四个类的对象转换成CharBuffer对象

另外两个参数start和end分别是子字符串的开始索引和结束索引的下一个位置 如将字符串 中的 转换成CharBuffer对象的语句如下

CharBuffercb=CharBuffer wrap( );

下面的代码演示了如何使用wrap方法将不同形式的字符串转换成CharBuffer对象

lishixin/Article/program/Java/hx/201311/26505

⑥ Java网络编程从入门到精通(5):使用InetAddress类的getHostName方法获得域

该方法可以得到远程主机的域名 也可以得到本机名 getHostName方法的定义如下

publicStringgetHostName()

下面是三种创建InetAddress对象的方式 在这三种方式中 getHostName返回的值是不同的

使用getLocalHost方法创建InetAddress对象

如果InetAddress对象是用getLocalHost方法创建的 getHostName返回的是本机名 如下面的代码所示

InetAddressaddress=InetAddress getLocalHost();System out println(address getHostName());//输出本机名

使用域名创建InetAddress对象

用域名作为getByName和getAllByName方法的参数调用这两个方法后 系统会自动记住这个域名 当调用getHostName方法时 就无需再访问DNS服务器 而是直接将这个域名返回 如下面的代码所示

InetAddressaddress=InetAddress getByName( );System out println(address getHostName());//无需访问DNS服务器 直接返回域名

使用IP地址创建InetAddress对象

使用IP地址创建InetAddress对象时(getByName getAllByName和getByAddress方法都可以通过IP地址创建InetAddress对象) 并不需要访问DNS服务器 因此 通过DNS服务器查找域名的工作就由getHostName方法来完成 如果这个IP地址不存在或DNS服务器不允许进行IP地址和域名的映射 getHostName方法就直接返回这个IP地址 如下面的代码所示

InetAddressaddress=InetAddress getByName( );System out println(address getHostName());//需要访问DNS服务器才能得到域名InetAddressaddress=InetAddress getByName( );//IP地址不存在System out println(address getHostName());//直接返回IP地址

从上面的三种情况可以看出 只有通过使用IP地址创建的InetAddress对象调用getHostName方法时才访问DNS服务器 在其他情况 getHostName方法并不会访问DNS服务器 而是直接将域名或本机名返回 下面的代码演示了在不同情况下如何使用getHostName方法 并计算了各种情况所需的毫秒数

package mynet;import *;publicclass DomainName{publicstaticvoidmain(String[]args)throwsException{longtime= ;//得到本机名InetAddressaddress =InetAddress getLocalHost();System out println( 本机名 +address getHostName());//直接返回域名InetAddressaddress =InetAddress getByName( );time=System currentTimeMillis();System out print( 直接得到域名 +address getHostName());System out println( 所用时间 +String valueOf(System currentTimeMillis() time)+ 毫秒 );//通过DNS查找域名InetAddressaddress =InetAddress getByName( ); System out println( address : +address );//域名为空time=System currentTimeMillis();System out print( 通过DNS查找域名 +address getHostName());System out println( 所用时间 +String valueOf(System currentTimeMillis() time)+ 毫秒 ); System out println( address : +address );//同时输出域名和IP地址}}

运行结果

本机名 ComputerName直接得到域名 所用时间 毫秒address :/ 通过DNS查找域名 bigip o所用时间 毫秒address :bigip o/

lishixin/Article/program/Java/hx/201311/26413

阅读全文

与java网络编程精解源代码相关的资料

热点内容
程序员毕设可以攻哪个方向 浏览:427
毛绒玩具怎么压缩 浏览:376
拖拉式编程教学视频 浏览:793
服务器坏了硬盘数据如何取出 浏览:602
体积加密度等于质量吗 浏览:608
如何执行命令 浏览:859
速卖通指标源码 浏览:179
linux切换root登录 浏览:925
什么是有效的服务器地址 浏览:825
交通银行app如何信用卡额度查询 浏览:479
asp程序员收入 浏览:334
无线有密码显示未加密 浏览:212
检查服务器地址命令 浏览:599
编译过程和解释过程的图表形式 浏览:837
文明重启如何弄自己的服务器免费 浏览:912
服务器权限不足如何解决 浏览:373
少儿编程乐高主要是学什么 浏览:674
张家口人社app如何实名认证 浏览:296
淘宝图片怎么设置加密 浏览:314
pdf拼接器 浏览:786