目录
简述
1.1网络基础
背景
TCP/IP网络模型
IP地址与InetAddress类
套接字
1.2 UDP协议网络程序
概述
DatagramPacket类
主要构造方法
常用方法
DatagramSocket类
主要构造方法
?常用方法
创建UDP服务器端程序
?示例
创建UDP客户端程序
简述
与网络编程有关的基本API位于Java.NET包中,其中包含基本的网络编程实现,该包是网络编程的基础。Java.NET包既包含基本的网络编程类,也包含封装后专门处理WEB相关的处理类。
1.1网络基础
背景
Java的网络通信可以使用TCP、IP、UDP等协议。网络程序设计就是开发为用户提供网络服务的实用程序,如网络通信、股票行情等。
TCP/IP网络模型
与OSI参考模型不同,TCP/IP参考模型只有4层,从下向上依次是网络接口层、网际层、传输层和应用层。
网络接口层:包括用于协作IP数据在已有网络介质上传输的协议。
网际层:对应于OSI七层参考模型的网络层。包含IP协议、RIP协议,负责数据的包装、寻址和路由。同时还包含网间控制报文协议ICMP用于提供网络诊断信息。
传输层:对应于OSI七层参考模型的传输层,停供两种端到端的通信服务。其中TCP协议提供可靠的数据流运输服务,UDP协议提供不可靠的用户数据包服务。
应用层:对应于OSI七层参考模型的应用层和表达层。
IP地址与InetAddress类
互联网上的每一台计算机都有一个唯一的表示自己的标记,即IP地址。
IP地址使用32位长度二进制数据表示,大部分IP地址都是以十进制的数据形式表示的。
IP地址分类中127.X.X.X是保留地址,用作循环测试,在开发中经常使用127.0.0.1表示本机的IP地址。
IP地址有IPv4和IPv6两类,由于IPv4已结无法满足当今互联网上的主机数量的需求,所以产生了IPv6,。IPv6能容纳更多的主机。
InetAddress类主要表示IP地址,其包含两个子类Inet4Address和Inet6Address,分别代表IPv4和IPv6。
套接字
套接字是通信的基石,是支持TCP/IP协议网络通信的基本操作单元。可以将套接字看做不同主机间的进程进行双向通信的端点,其构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常与同一个域中的套接字交换数据。
套接字之间的连接过程可以分为三个步骤:服务器监听、客户端请求和连接确认。
服务器监听是指服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
连接确认是指当前服务器端套接字监听到或接收到客户端套接字的连接请求,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立成功。服务器端套接字继续处于监听状态,接收其他客户端套接字的连接请求。
1.2 UDP协议网络程序
概述
- UDP是一种无连接的协议,每一个数据包都是一个独立的信息,包括完整的源地址或目的地址。
- 由于UDP在网络上是以任何可能的路径传往目的地的,因此能否到达目的地、到达目的地的时间及内容的正确性都是不能被保证的。
- 使用UDP时,每个数据包中都给出了完整的地址信息,无须再建立发送方和接收方的连接。
- 使用UDP传输数据是有大小限制的,每个被传输的数据包必须限定在64KB之内。
- UDP是一个不可靠的协议,发送方所发送的数据包不一定以相同的次序到达接收方。
- 在Java.net包中提供了两个类:DatagramSocket和DatagramPacket,用于支持数据包通信。
DatagramPacket类
主要构造方法
public DatagramPacket(byte[] buf,int length)
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
public DatagramPacket(byte[] buf,int offset,int length)
public DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)
public DatagramPacket(byte[] buf,int offset,int length,SocketAddress address) throws SocketException
常用方法
public InetAddress getAddress()? ? ? ?返回发送或接收数据包的主机地址
public byte[] getData()? ? ?返回数据包内容
public int getLength()? ? 返回接收或发送的数据长度
public int getPort()? ? 返回发送或接收数据包的远程主机端口
public void setAddress(InetAddress iaddr)? ? 设置发送或接收数据包的主机地址
public void setData(byte[] buf)? ? 设置数据包内容
public void setLength(int length)? ? 设置接收或发送的数据长度
public void setPort(int iport)? ? 设置发送或接收数据包的远程主机端口
DatagramSocket类
主要构造方法
?常用方法
public void connect(InetAddress address, int port)? ? ? ?建立套接字连接
public void disconnect()? ? 断开套接字连接
public InetAddress getInetAddress()? ? 返回已连接套接字的地址
public InetAddress getLocalAddress()? ? 返回套接字绑定的本地地址
public int getLocalPort()? ? ?返回套接字绑定的本地端口
public int getPort()? ? ?返回已连接套接字的端口
public void receive(DatagramPacket p) throws?IOException? ?接收数据包
public void send(DatagramPacket p) throws?IOException? ?发送数据包
创建UDP服务器端程序
?示例
服务器端接收客户端发出来的空数据包(代表客户端发出请求),由接收的数据包获得客户端的IP地址和端口号。然后将服务器端的当前时间以数据包的形式发给客户端,当超过10个客户端请求后,服务器端自动关闭。
/**
* @author asus
*/
public class UDPServer {
private DatagramSocket socket;
private int counter = 1;
public UDPServer() throws IOException {
socket = new DatagramSocket(9080);
}
public void run(){
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try{
do {
byte[] buf = new byte[19];
DatagramPacket packet = new DatagramPacket(buf,buf.length);
socket.receive(packet);
String time = formatter.format(new Date());
buf = time.getBytes();
packet = new DatagramPacket(buf, buf.length);
socket.send(packet);
} while (counter < 10);
} catch (IOException e){
e.printStackTrace();
}
socket.close();
}
public static void main(String[] args) {
try {
System.out.println("服务器已经启动!");
new UDPServer().run();
System.out.println("服务器已经关闭!");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行结果如下:
创建UDP客户端程序
示例
客户端首先发送请求数据包(空的数据包),然后等待接口服务器端传回来的带有服务器当前时间的数据包,显示服务器发送时的时间之后关闭
public class UDPClient {
private DatagramSocket socket;
private String serverIP = "127.0.0.1";
public UDPClient() throws SocketException {
socket = new DatagramSocket();
}
public void setSocketIP(String serverIP){
this.serverIP = serverIP;
}
public void run() {
try {
byte[] buf = new byte[19];
InetAddress address = InetAddress.getByName(serverIP);
DatagramPacket packet = new DatagramPacket(buf,buf.length,address, 9080);
socket.send(packet);
packet = new DatagramPacket(buf,buf.length);
socket.receive(packet);
String received = new String(packet.getData());
System.out.println("服务器端时间:" + received);
socket.close();
} catch (UnknownHostException e){
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
System.out.println("客户端启动,请求获取服务器当前时间的信息...");
new UDPClient().run();
System.out.println("客户端已获得服务器当前时间,自动关闭!");
} catch (SocketException e){
e.printStackTrace();
}
}
}
|