1. 体系结构
计算机网络各层及其协议的集合,称为网络的体系结构。目前公认的计算机网络体系结构有概念清楚理论完善的OSI七层协议结构和实际上广泛应用的TCP/IP四层体系结构。
2. 各层概述
- 应用层:直接为用户的程序提供服务,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等。
- 运输层:负责向两个主机中进程之间的通信提供服务,主要使用面向连接的TCP协议和无连接的UDP协议。
- 网络层:负责为分组交换网上不同主机提供地址交付的通信服务,该层使用IP协议,所以在该层传送的数据称之为IP数据报。路由器工作在该层。
- 数据链路层:负责将IP数据报在相邻的节点之间传输,该层将IP数据报封装成帧,将IP地址转换为MAC硬件地址封装在帧中进行节点间的传输。网桥,桥接器和交换机都工作在该层。
- 物理层:包括数据传输的介质和电气特性,包括电缆,光缆,光信号,电信号的标准等。转发器,信号放大器都工作在该层。
- 每一层的实际运作对上一层都是透明的。
- 应用程序间通过网络交换数据,数据在发送方从上到下层层封装,通过物理层传输,到接收方又从下至上层层拆封还原原始数据。
Java中的网络通讯
1. IP地址
1.1 概述
IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
1.2 域名解析
为了方便记忆,出现域名,并且需要从域名转化为IP地址的协议或服务,该服务就是域名解析(DNS)。
特殊地址
- 127.0.0.1:本机回环地址。
- 主机号为全1:该网络广播地址。
1.3 InetAddress类
概述
- 该类没有构造器。
- 该类用于IP地址的封装。
方法
- 返回本机IP原始地址
byte[] getAddress() - 通过主机名或IP地址获取IP地址对象
static InetAddress[] getAllByName(String host)
static InetAddress getByAddress(byte[] addr)
static InetAddress getByAddress(String host, byte[] addr)
static InetAddress getByName(String host) - 获取主机IP地址或主机名
- static InetAddress getLocalHost()
String getHostAddress()
String getHostName()
示例
package net;import java.net.InetAddress;import java.net.UnknownHostException;public class InetDemo {public static void main(String[] args) throws UnknownHostException {// 获取本机IP对象InetAddress iphost = InetAddress. getLocalHost();String ipstr = iphost.getHostAddress(); // "192.168.1.22"String ipname = iphost.getHostName(); // "YH-PC"// 获取指定IP对象InetAddress ip = InetAddress.getByName("192.168.1.1");ipstr = ip.getHostAddress(); // "192.168.1.1"ipname = ip.getHostName(); // "192.168.1.1"// 获取指定主机的IP对象InetAddress[] ips = InetAddress.getAllByName("www.google.com.hk");for (int i = 0; i < ips.length; i++) {ipstr = ips[i].getHostAddress();ipname = ips[i].getHostName();System.out.println( ipstr);System.out.println( ipname);// 173.194.120.88// www.google.com.hk// 216.239.32.39// www.google.com.hk}}}
2. 端口号
- 全称为TCP/IP端口,是应用层用于识别通讯进程的接口。
- 有效端口:0~65535,系统使用或保留的端口是:0~1024。
3. 传输层协议
3.1 UDP协议
- 无连接的,不保证可靠交付,只能提供尽最大努力交付。
- 无需创建链接,速度较快。
- 支持一对一,一对多,多对一,多对多通讯。
- 面向报文的通信。
- 没有拥塞控制,所以可能会有丢包,但是传输速率不受影响,延时较小,适合实时性要求高的网络视频,聊天等。
3.2 TCP协议
- 面向连接的,提供可靠交付服务。
- TCP链接只能有两个端点,所以只能是点对点(一对一)通讯。
- TCP提供全双工通信,适合大数据量的传输。
- 面向字节流的通信。
- 需要通过三次握手建立链接,速度稍慢。
4. 通讯过程
- 明确IP地址。
- 明确通讯端口。
- 明确使用协议。
- 建立Socket(套接字,类似于通信链接的端口,插口)通信服务。
- 建立通信数据报文Package。
- 使用Socket来发送或接收报文。
UDP协议相关API
1. DatagramSocket类
概述
该类用于UDP通讯套接字的建立。
构造器
- 绑定本地主机创建套接字
DatagramSocket()
DatagramSocket(int port) - 绑定指定主机创建套接字(当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自指定地址的报文)
DatagramSocket(DatagramSocketImpl impl)
DatagramSocket(int port, InetAddress laddr)
DatagramSocket(SocketAddress bindaddr)
常用方法
- 将套接字绑定到特定的IP地址和端口号
void bind(SocketAddress addr) - 关闭该套接字
void close() - 将该套接字连接至远程地址(用于建立单向通讯)
void connect(InetAddress address, int port)
void connect(SocketAddress addr) - 断开链接
void disconnect() - 获取与该套接字连接的地址
InetAddress getInetAddress()
SocketAddress getRemoteSocketAddress() - 获取与该套接字连接的端口号
int getPort() - 获取与该套接字绑定的本地地址
InetAddress getLocalAddress()
SocketAddress getLocalSocketAddress() - 获取与该套接字绑定的本地端口号
int getLocalPort() - 判断套接字状态
boolean isBound()
boolean isClosed()
boolean isConnected() - 接收和发送
void receive(DatagramPacket p)
void send(DatagramPacket p) - 设置接收和发送缓冲区大小以及超时限制
void setReceiveBufferSize(int size)
void setSendBufferSize(int size)
void setSoTimeout(int timeout)
2. DatagramPacket类
概述
该类用于数据报文的建立。
构造器
- 建立发送报文
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
DatagramPacket(byte[] buf, int length, SocketAddress address) - 建立接收报文
DatagramPacket(byte[] buf, int length)
DatagramPacket(byte[] buf, int offset, int length)
常用方法
- 获取该数据报发送的目的地址或接收的源地址。
InetAddress getAddress()
SocketAddress getSocketAddress()
int getPort() - 获取数据报数据长度和偏移量
int getLength()
int getOffset() - 设置数据报发送地址
void setAddress(InetAddress iaddr)
void setSocketAddress(SocketAddress address)
void setPort(int iport) - 设置数据报数据
void setData(byte[] buf)
void setData(byte[] buf, int offset, int length)
void setLength(int length)
3. 通信步骤
发送端
- 建立套接字。
- 明确目标地址和端口号,建立带地址的数据报文。
- 使用套接字发送数据报文。
- 关闭套接字。
接收端
- 明确端口号,建立带端口号套接字。
- 建立接收的数据报文。
- 使用套接字接收数据报文。
- 关闭套接字。
4. 示例
UDP发送端
package net;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDP_Send {public static void main(String[] args) throws IOException {/** UDP发送端*/System.out.println( "UDP发送端");// 获取本地IP地址InetAddress ip = InetAddress.getLocalHost();System.out.println( "Destination IP = " + ip.getHostAddress());// 1. 建立UDP的socketDatagramSocket ds = new DatagramSocket();// 2. 将数据封装到数据包中byte[] buf = "hello UDP!".getBytes();DatagramPacket dp = new DatagramPacket( buf, buf.length , ip , 22222);// 3. 使用Socket对象的send方法将数据包发送出去ds.send(dp);// 4. 关闭资源。ds.close();}}
UDP接收端
package net;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDP_Receive {public static void main(String[] args) throws IOException {/** UDP接收端*/System.out.println( "UDP接收端");// 1. 建立UDP的socketDatagramSocket ds = new DatagramSocket(22222);// 2. 定义数据包方便接收数据byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket( buf, buf.length );// 3. 使用Socket对象的receive方法阻塞接收数据ds.receive(dp);// 4. 获取接收到的数据String ip = dp.getAddress().getHostAddress();int port = dp.getPort();String data = new String( dp.getData(), 0, dp.getLength());System.out.println( "ip = " + ip + "\nport = " + port + "\ndata = " + data );// 4. 关闭资源。ds.close();}}
实例
聊天室程序
package net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;public class Test_ChatByUDP {public static void main(String[] args) throws SocketException, UnknownHostException {// 创建用于发送和接收的套接字,端口33333只用于聊天室接收程序。DatagramSocket sendDs = new DatagramSocket();DatagramSocket receDs = new DatagramSocket(33333);// 创建广播地址InetAddress ip = InetAddress.getByName("192.168.1.255");// 创建发送和接收对象Send sd = new Send( sendDs, ip);Rece rc = new Rece( receDs);new Thread( sd).start();new Thread( rc).start();}}class Send implements Runnable {private DatagramSocket ds;private InetAddress ip;public Send(DatagramSocket ds, InetAddress ip) {super();this.ds = ds;this.ip = ip;}@Overridepublic void run() {// 读取键盘录入BufferedReader br = new BufferedReader( new InputStreamReader(System.in ));String str = null;try {while (( str = br.readLine()) != null) {// 发送键盘录入的字符DatagramPacket dp = new DatagramPacket(str.getBytes(), str .length(), ip , 33333);ds.send( dp);if ( "exit".equals(str )) {break;} else if ( "close".equals(str )) {break;}}ds.close();} catch (IOException e) {e.printStackTrace();}}}class Rece implements Runnable {private DatagramSocket ds;public Rece(DatagramSocket ds) {super();this.ds = ds;}@Overridepublic void run() {while ( true) {byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket( buf, buf.length );try {// 阻塞接收ds.receive( dp);} catch (IOException e) {e.printStackTrace();}// 获取发送方地址String ip = dp.getAddress().getHostAddress();String str = new String( dp.getData(), 0, dp.getLength());int port = dp.getPort();if ("exit".equals( str)) {// 判断发送字符System. out.println(ip + ":" + port + " 离开了聊天室!" );} else if ("close".equals( str)) {System. out.println(ip + ":" + port + " 请求关闭聊天室!" );break;} else {System. out.println(ip + ":" + port + " 说:" + str);}}ds.close();System.out.println( "聊天室已关闭!" );}}
1. 体系结构
计算机网络各层及其协议的集合,称为网络的体系结构。目前公认的计算机网络体系结构有概念清楚理论完善的OSI七层协议结构和实际上广泛应用的TCP/IP四层体系结构。
2. 各层概述
- 应用层:直接为用户的程序提供服务,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等。
- 运输层:负责向两个主机中进程之间的通信提供服务,主要使用面向连接的TCP协议和无连接的UDP协议。
- 网络层:负责为分组交换网上不同主机提供地址交付的通信服务,该层使用IP协议,所以在该层传送的数据称之为IP数据报。路由器工作在该层。
- 数据链路层:负责将IP数据报在相邻的节点之间传输,该层将IP数据报封装成帧,将IP地址转换为MAC硬件地址封装在帧中进行节点间的传输。网桥,桥接器和交换机都工作在该层。
- 物理层:包括数据传输的介质和电气特性,包括电缆,光缆,光信号,电信号的标准等。转发器,信号放大器都工作在该层。
- 每一层的实际运作对上一层都是透明的。
- 应用程序间通过网络交换数据,数据在发送方从上到下层层封装,通过物理层传输,到接收方又从下至上层层拆封还原原始数据。
Java中的网络通讯
1. IP地址
1.1 概述
IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
1.2 域名解析
为了方便记忆,出现域名,并且需要从域名转化为IP地址的协议或服务,该服务就是域名解析(DNS)。
特殊地址
- 127.0.0.1:本机回环地址。
- 主机号为全1:该网络广播地址。
1.3 InetAddress类
概述
- 该类没有构造器。
- 该类用于IP地址的封装。
方法
- 返回本机IP原始地址
byte[] getAddress() - 通过主机名或IP地址获取IP地址对象
static InetAddress[] getAllByName(String host)
static InetAddress getByAddress(byte[] addr)
static InetAddress getByAddress(String host, byte[] addr)
static InetAddress getByName(String host) - 获取主机IP地址或主机名
- static InetAddress getLocalHost()
String getHostAddress()
String getHostName()
示例
package net;import java.net.InetAddress;import java.net.UnknownHostException;public class InetDemo {public static void main(String[] args) throws UnknownHostException {// 获取本机IP对象InetAddress iphost = InetAddress. getLocalHost();String ipstr = iphost.getHostAddress(); // "192.168.1.22"String ipname = iphost.getHostName(); // "YH-PC"// 获取指定IP对象InetAddress ip = InetAddress.getByName("192.168.1.1");ipstr = ip.getHostAddress(); // "192.168.1.1"ipname = ip.getHostName(); // "192.168.1.1"// 获取指定主机的IP对象InetAddress[] ips = InetAddress.getAllByName("www.google.com.hk");for (int i = 0; i < ips.length; i++) {ipstr = ips[i].getHostAddress();ipname = ips[i].getHostName();System.out.println( ipstr);System.out.println( ipname);// 173.194.120.88// www.google.com.hk// 216.239.32.39// www.google.com.hk}}}
2. 端口号
- 全称为TCP/IP端口,是应用层用于识别通讯进程的接口。
- 有效端口:0~65535,系统使用或保留的端口是:0~1024。
3. 传输层协议
3.1 UDP协议
- 无连接的,不保证可靠交付,只能提供尽最大努力交付。
- 无需创建链接,速度较快。
- 支持一对一,一对多,多对一,多对多通讯。
- 面向报文的通信。
- 没有拥塞控制,所以可能会有丢包,但是传输速率不受影响,延时较小,适合实时性要求高的网络视频,聊天等。
3.2 TCP协议
- 面向连接的,提供可靠交付服务。
- TCP链接只能有两个端点,所以只能是点对点(一对一)通讯。
- TCP提供全双工通信,适合大数据量的传输。
- 面向字节流的通信。
- 需要通过三次握手建立链接,速度稍慢。
4. 通讯过程
- 明确IP地址。
- 明确通讯端口。
- 明确使用协议。
- 建立Socket(套接字,类似于通信链接的端口,插口)通信服务。
- 建立通信数据报文Package。
- 使用Socket来发送或接收报文。
UDP协议相关API
1. DatagramSocket类
概述
该类用于UDP通讯套接字的建立。
构造器
- 绑定本地主机创建套接字
DatagramSocket()
DatagramSocket(int port) - 绑定指定主机创建套接字(当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自指定地址的报文)
DatagramSocket(DatagramSocketImpl impl)
DatagramSocket(int port, InetAddress laddr)
DatagramSocket(SocketAddress bindaddr)
常用方法
- 将套接字绑定到特定的IP地址和端口号
void bind(SocketAddress addr) - 关闭该套接字
void close() - 将该套接字连接至远程地址(用于建立单向通讯)
void connect(InetAddress address, int port)
void connect(SocketAddress addr) - 断开链接
void disconnect() - 获取与该套接字连接的地址
InetAddress getInetAddress()
SocketAddress getRemoteSocketAddress() - 获取与该套接字连接的端口号
int getPort() - 获取与该套接字绑定的本地地址
InetAddress getLocalAddress()
SocketAddress getLocalSocketAddress() - 获取与该套接字绑定的本地端口号
int getLocalPort() - 判断套接字状态
boolean isBound()
boolean isClosed()
boolean isConnected() - 接收和发送
void receive(DatagramPacket p)
void send(DatagramPacket p) - 设置接收和发送缓冲区大小以及超时限制
void setReceiveBufferSize(int size)
void setSendBufferSize(int size)
void setSoTimeout(int timeout)
2. DatagramPacket类
概述
该类用于数据报文的建立。
构造器
- 建立发送报文
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
DatagramPacket(byte[] buf, int length, SocketAddress address) - 建立接收报文
DatagramPacket(byte[] buf, int length)
DatagramPacket(byte[] buf, int offset, int length)
常用方法
- 获取该数据报发送的目的地址或接收的源地址。
InetAddress getAddress()
SocketAddress getSocketAddress()
int getPort() - 获取数据报数据长度和偏移量
int getLength()
int getOffset() - 设置数据报发送地址
void setAddress(InetAddress iaddr)
void setSocketAddress(SocketAddress address)
void setPort(int iport) - 设置数据报数据
void setData(byte[] buf)
void setData(byte[] buf, int offset, int length)
void setLength(int length)
3. 通信步骤
发送端
- 建立套接字。
- 明确目标地址和端口号,建立带地址的数据报文。
- 使用套接字发送数据报文。
- 关闭套接字。
接收端
- 明确端口号,建立带端口号套接字。
- 建立接收的数据报文。
- 使用套接字接收数据报文。
- 关闭套接字。
4. 示例
UDP发送端
package net;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDP_Send {public static void main(String[] args) throws IOException {/** UDP发送端*/System.out.println( "UDP发送端");// 获取本地IP地址InetAddress ip = InetAddress.getLocalHost();System.out.println( "Destination IP = " + ip.getHostAddress());// 1. 建立UDP的socketDatagramSocket ds = new DatagramSocket();// 2. 将数据封装到数据包中byte[] buf = "hello UDP!".getBytes();DatagramPacket dp = new DatagramPacket( buf, buf.length , ip , 22222);// 3. 使用Socket对象的send方法将数据包发送出去ds.send(dp);// 4. 关闭资源。ds.close();}}
UDP接收端
package net;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDP_Receive {public static void main(String[] args) throws IOException {/** UDP接收端*/System.out.println( "UDP接收端");// 1. 建立UDP的socketDatagramSocket ds = new DatagramSocket(22222);// 2. 定义数据包方便接收数据byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket( buf, buf.length );// 3. 使用Socket对象的receive方法阻塞接收数据ds.receive(dp);// 4. 获取接收到的数据String ip = dp.getAddress().getHostAddress();int port = dp.getPort();String data = new String( dp.getData(), 0, dp.getLength());System.out.println( "ip = " + ip + "\nport = " + port + "\ndata = " + data );// 4. 关闭资源。ds.close();}}
实例
聊天室程序
package net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;public class Test_ChatByUDP {public static void main(String[] args) throws SocketException, UnknownHostException {// 创建用于发送和接收的套接字,端口33333只用于聊天室接收程序。DatagramSocket sendDs = new DatagramSocket();DatagramSocket receDs = new DatagramSocket(33333);// 创建广播地址InetAddress ip = InetAddress.getByName("192.168.1.255");// 创建发送和接收对象Send sd = new Send( sendDs, ip);Rece rc = new Rece( receDs);new Thread( sd).start();new Thread( rc).start();}}class Send implements Runnable {private DatagramSocket ds;private InetAddress ip;public Send(DatagramSocket ds, InetAddress ip) {super();this.ds = ds;this.ip = ip;}@Overridepublic void run() {// 读取键盘录入BufferedReader br = new BufferedReader( new InputStreamReader(System.in ));String str = null;try {while (( str = br.readLine()) != null) {// 发送键盘录入的字符DatagramPacket dp = new DatagramPacket(str.getBytes(), str .length(), ip , 33333);ds.send( dp);if ( "exit".equals(str )) {break;} else if ( "close".equals(str )) {break;}}ds.close();} catch (IOException e) {e.printStackTrace();}}}class Rece implements Runnable {private DatagramSocket ds;public Rece(DatagramSocket ds) {super();this.ds = ds;}@Overridepublic void run() {while ( true) {byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket( buf, buf.length );try {// 阻塞接收ds.receive( dp);} catch (IOException e) {e.printStackTrace();}// 获取发送方地址String ip = dp.getAddress().getHostAddress();String str = new String( dp.getData(), 0, dp.getLength());int port = dp.getPort();if ("exit".equals( str)) {// 判断发送字符System. out.println(ip + ":" + port + " 离开了聊天室!" );} else if ("close".equals( str)) {System. out.println(ip + ":" + port + " 请求关闭聊天室!" );break;} else {System. out.println(ip + ":" + port + " 说:" + str);}}ds.close();System.out.println( "聊天室已关闭!" );}}
本文详细介绍了Java中的网络编程,包括IP地址、域名解析、端口号、传输层协议等内容。并提供了UDP协议相关的API介绍及聊天室程序实例。

4780

被折叠的 条评论
为什么被折叠?



