Java语言的网络性能也是其被广为使用的重要原因,用Java开发网络软件非常方便且功能强大。 Java用于开发网络程序的API均位于包java.net和javax.net中。类InetAddress在Java网络编程中扮演重要角色。同许多网络程序一样,Java编程中必然也要提到套接字(Socket)的概念以及相应的Network API操纵套接字,并且其另一种情况下进行的网络通讯——非连接的UDP协议。也即分为面向连接的流式套接字和面向非连接的UDP数据报。 一、InetAddress类简介 InetAddress描述了32位(即显然是说的是IPv4)或128位(即显然是说的是IPv6)IP地址,要完成这个功能,InetAddress类主要依靠Inet4Address 和 Inet6Address两个支持类。 这三个类是继承关系,InetAddrress是父类,Inet4Address 和 Inet6Address是子类. 以通过下面的5个静态方法来创建一个InetAddress对象或InetAddress数组 : (1)getAllByName(String host)方法 (2)getByAddress(byte [ ] addr)方法 (3)getByAddress(String host, byte [ ] addr)方法 (4)getByName(String host)方法 (5)getLocalHost()方法 上面讲到的方法均提到返回一个或多个InetAddress对象的引用 InetAddress和它的子类型对象处理主机名到主机IPv4或IPv6地址的转换 例:InetAddress ia = InetAddress.getByName("www.sun.com");
import java.net.*;
/**
*演示InetAddress类的基本使用
*/
public class InetAddressDemo{
public static void main(String[] args){
try{
//使用域名创建对象
InetAddress inetAd=InetAddress.getByName("www.163.com");//getByName是InetAddress类的静态方法
System.out.println(inetAd);
//使用IP创建对象
InetAddress inetAd2=InetAddress.getByName("127.0.0.1");
System.out.println(inetAd2);
//获得本机地址对象
InetAddress inetAd3=InetAddress.getLocalHost();
System.out.println(inetAd3);
//获得对象中储存的域名
String host=inetAd3.getHostName();
System.out.println("域名: "+host);
//获得对象中储存的IP
String ip=inetAd3.getHostAddress();
System.out.println("IP: "+ip);
}
catch(Exception e){
}
}
}
运行结果如下:
二、面向流式的套接字
1 什么是套接字
Socket可以看成在两个程序进行通信连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中
在两个网络应用程序之间发送和接收信息时需要建立一个可靠的连接,流套接字依靠TCP协议来保证信息正确到达目的地。
在C/S程序中,包括了相关联的三个类:
InetAddress
Socket
ServerSocket
2 ServerSocket类
服务器程序套接字
构造函数:
ServerSocket(int port);port参数传递端口号 ,如果在这时出现错误将抛出IOException异常对象
接下来服务程序进入无限循环之中。
无限循环从调用ServerSocket的accept()方法开始,在调用开始后accept()方法将导致调用线程阻塞直到连接建立。在建立连接后accept()返回一个最近创建的Socket对象,该Socket对象绑定了客户程序的IP地址或端口号。
3 Socket类
当客户程序需要与服务器程序通信时,客户程序在客户机创建一个socket对象
构造函数:
Socket(InetAddress addr, int port);
Socket(String host, int port);
可能通过调用Socket的 getInputStream()方法从服务程序获得输入流读传送来的信息
可能通过调用Socket的 getOutputStream()方法获得输出流来发送消息
三、面向非连接的数据报
1 UDP简介 (User Datagram Protocal)
UDP位于第四层——传输层,处于IP协议的上一层。
UDP有不提供数据报分组、组装以及不能对数据报排序的缺点。
当报文发送之后,是无法得知其是否安全完整到达的。
2 DatagramPacket类
DatagramPacket类用于处理报文,它将Byte数组、目标地址和目标端口等数据包装成报文或者将报文拆卸成Byte数组
构造函数:
1)DatagramPacket(byte [ ] buf, int length);
其中buf参数包含了一个对保存自寻址数据报信息的字节数组的引用,length表示字节数组的长度
可以通过调用方法setAddress(InetAddress addr)和setPort(int port)添加上数据报地址和端口信息
2)DatagramPacket(byte [ ] buf, int length, InetAddress addr, int port)
DatagramPacket的常用方法有:
getAddress()、setAddress(InetAddress) 得到、设置数据报地址。
getData()、setData(byte [ ] buf) 得到、设置数据报内容。
getLength()、setLength(ing length) 得到、设置数据报长度。
getPort()、setPort(int port) 得到、设置端口号。
3 DatagramSocket类
DatagramSocket类在客户端创建数据报套接字与服务器端进行通信连接,并发送和接受数据报套接字
DatagramSocket构造方法:
DatagramSocket() 创建数据报套接字,绑定到本地主机任意存在的端口。
DatagramSocket(int port) 创建数据报套接字,绑定到本地主机指定端口。
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,绑定到指定本地地址
常用方法:
connect(InetAddress address, int port) 连接指定地址。
disconnect() 断开套接字连接。
close() 关闭数据报套接字。
getInetAddress() 得到套接字所连接的地址。
getLocalAddress() 得到套接字绑定的主机地址。
getLocalPort() 得到套接字绑定的主机端口号。
getPort() 得到套接字的端口号。
reseive(DatagramPacket p) 接收数据报。
send(DatagramPacket p) 发送数据报。
如下面的程序:DatagramDemo.java
import java.io.*;
import java.net.*;
class DatagramDemo{
public static void main(String[] args){
String host="localhost";
if(args.length==1){
System.out.println("args.length=="+args.length);
host=args[0];
}
DatagramSocket s=null;
try{
s=new DatagramSocket();
byte[] buffer;
buffer=new String("Send me a datagram").getBytes();
InetAddress inetAddr=InetAddress.getByName(host);
DatagramPacket dataGramPacket=new DatagramPacket(buffer,buffer.length,inetAddr,10000);//你将这里改为1000端口,再看运行的MCseverClient会不会收到报文
s.send(dataGramPacket);
byte[] buffer2=new byte[100];
dataGramPacket=new DatagramPacket(buffer2,buffer2.length,inetAddr,1000);
s.receive(dataGramPacket);
System.out.println(new String(dataGramPacket.getData()));
}
catch(IOException e){
System.out.println(e.toString());
}
finally{
if(s!=null)
s.close();
}
}
}
注意:上面程序的运行结果是在下面的程序(MCseverClient.java)运行界面中看到,也即要建立起服务器客户端 import java.io.*;
import java.net.*;
class MCseverClient{
public static void main(String[] args)throws IOException{
MulticastSocket s=new MulticastSocket(10000);//MulticastSocket ???服务器端开放多个端口?
InetAddress group=InetAddress.getByName("231.0.0.1");
s.joinGroup(group);
for(int i=0;i<10;i++){
byte[] buffer=new byte[256];
DatagramPacket datagramPacket=new DatagramPacket(buffer,buffer.length);
s.receive(datagramPacket);
byte[] buffer2=new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(),0,buffer2,0,datagramPacket.getLength());
System.out.println(new String(buffer2));
/*if(datagramPacket.getData()!=null){
byte[] sendStr;
sendStr=new String("I received from "+datagramPacket.getAddress()).getBytes();
DatagramPacket datagramSend=new DatagramPacket(sendStr,sendStr.length,datagramPacket.getAddress(),1000);
DatagramSocket sendSock=new DatagramSocket();
sendSock.send(datagramSend);
}*/
}
s.leaveGroup(group);
s.close();
}
}
4 多点传送和MulticastSocket类
如果服务器程序要将同一信息发送给多个客户端,那么服务器程序和客户程序可以利用多点传送(multicasting)方式进行通信
网络API通过MulticastSocket类和MulticastSocket,以及一些辅助类(如NetworkInterface)支持多点传送