------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、概述:
Java语言是在网络环境下诞生的,所以Java语言虽然不能说是对于网络编程的支持最好的语言,但是必须说是一种对于网络编程提供良好支持的语言,使用Java语言进行网络编程将是一件比较轻松的工作。和网络编程有关的基本API位于java.net包中,该包中包含了基本的网络编程实现,该包是网络编程的基础。该包中既包含基础的网络编程类,也包含封装后的专门处理WEB相关的处理类。在此只介绍基础的网络编程类,一共分为三大部分学习,第一部分是网络的基本架构、第二部分是UDP编程、第三部分是TCP编程。
二、网络的基本架构
1. ISO/OSI的参考模型共有7层,由低层至高层分别为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。各层功能分别为:
(1)物理层
提供建立、维护和拆除物理链路所需的机械、电气、功能和规程的特性;提供有关在传输介质上传输非结构的位流
及物理链路故障检测指示。在这一层,数据还没有被组织,仅作为原始的位流或电气电压处理,单位是比特。
(2)数据链路层
负责在两个相邻结点间的线路上,无差错地传送以帧为单位的数据,并进行流量控制。每一帧包括一定数量的数据
和一些必要的控制信息。与物理层相似,数据链路层要负责建立、维持和释放数据链路的连接。在传送数据时,如
果接收点检测到所传数据中有差错,就要通知发方重发这一帧。
(3)网络层
为传输层实体提供端到端的交换网络数据传送功能,使得传输层摆脱路由选择、交换方式、拥挤控制等网络传输
细节;可以为传输层实体建立、维持和拆除一条或多条通信路径;对网络传输中发生的不可恢复的差错予以报告。
网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息——源站点和目的站点
地址的网络地址。
(4)传输层
为会话层实体提供透明、可靠的数据传输服务,保证端到端的数据完整性;选择网络层的最适宜的服务;提供建
立、维护和拆除传输连接功能。传输层根据通信子网的特性,最佳的利用网络资源,为两个端系统的会话层之间提
供建立、维护和取消传输连接的功能,并以可靠和经济的方式传输数据。在这一层,信息的传送单位是报文。
(5)会话层
为彼此合作的表示层实体提供建立、维护和结束会话连接的功能;完成通信进程的逻辑名字与物理名字间的对应;
提供会话管理服务。
(6)表示层
为应用层进程提供能解释所交换信息含义的一组服务,即将欲交换的数据从适合于某一用户的抽象语法,转换为
适合于OSI系统内部使用的传送语法,提供格式化的表示和转换数据服务。数据的压缩,解压缩,加密和解密等
工作都由表示层负责。
(7)应用层
提供OSI用户服务,即确定进程之间通信的性质,以满足用户需要以及提供网络与用户应用软件之间的接口服务。
简言之,各层的作用:
物理层:在物理媒体上传输原始的数据比特流。
数据链路层:将数据分成一个个数据帧,以数据帧为单位传输。有应有答,遇错重发。
网络层:将数据分成一定长度的分组,将分组穿过通信子网,从信源选择路径后传到信宿。
传输层:提供不具体网络的高效、经济、透明的端到端数据传输服务。
会话层:进程间的对话也称为会话,会话层管理不同主机上各进程间的对话。
表示层: 为应用层进程提供格式化的表示和转换数据服务。
应用层:提供应用程序访问OSI环境的手段。
三、UDP编程
网络通讯的方式除了TCP方式以外,有一种实现的方式就是UDP方式。UDP(User Datagram Protocol),中文意思是用户数据报协议,方式类似于发短信息,是一种物美价廉的通讯方式,使用该种方式无需建立专用的虚拟连接,由于无需建立专用的连接,所以对于服务器的压力要比TCP小很多,所以也是一种常见的网络编程方式。但是使用该种方式最大的不足是传输不可靠,当然也不是说经常丢失,就像大家发短信息一样,理论上存在收不到的可能,这种可能性可能是1%,反正比较小,但是由于这种可能的存在,所以平时我们都觉得重要的事情还是打个电话吧(类似TCP方式),一般的事情才发短信息(类似UDP方式)。网络编程中也是这样,必须要求可靠传输的信息一般使用TCP方式实现,一般的数据才使用UDP方式实现。
UDP方式的网络编程也在Java语言中获得了良好的支持,由于其在传输数据的过程中不需要建立专用的连接等特点,所以在Java API中设计的实现结构和TCP方式不太一样。当然,需要使用的类还是包含在java.net包中。
首先来介绍一个基础的网络类——InetAddress类。该类的功能是代表一个IP地址,并且将IP地址和域名相关的操作方法包含在该类的内部。关于该类的使用,下面通过一个基础的代码示例演示该类的使用,代码如下:
import java.net.*;
/**
* 演示InetAddress类的基本使用
*/
public classInetAddressDemo
{
public static void main(String[] args)
{
try
{
//使用域名创建对象
InetAddress inet1 =InetAddress.getByName("www.163.com");
System.out.println(inet1);
//使用IP创建对象
InetAddress inet2 =InetAddress.getByName("127.0.0.1");
System.out.println(inet2);
//获得本机地址对象
InetAddress inet3 =InetAddress.getLocalHost();
System.out.println(inet3);
//获得对象中存储的域名
String host =inet3.getHostName();
System.out.println("域名:" +host);
//获得对象中存储的IP
String ip =inet3.getHostAddress();
System.out.println("IP:"+ ip);
}
catch(Exception e){}
}
}
在该示例代码中,演示了InetAddress类的基本使用,并使用了该类中的几个常用方法,该代码的执行结果是:
www.163.com/220.181.28.50
/127.0.0.1
chen/192.168.1.100
域名:chen
IP:192.168.1.100
下面介绍一下UDP方式的网络编程中,客户端和服务器端的实现步骤,以及通过基础的示例演示UDP方式的网络编程在Java语言中的实现方式。
通过udp传输方式,将一段文字数据发送出去。定义一个udp发送端:
1,建立updsocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4,关闭资源。
class UdpSend
{
public static void main(String[] args)throws Exception
{
//1,创建udp服务。通过DatagramSocket对象。
DatagramSocket ds = newDatagramSocket(8888);
//2,确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, intport)
byte[] buf = "udp ge menlai le ".getBytes();
DatagramPacket dp =
newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000);
//3,通过socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);
//4,关闭资源。
ds.close();
}
}
定义udp的接收端:
1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。方便于明确哪些数据过来该应用程序可以处理。
2,定义一个数据包,因为要存储接收到的字节数据。因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
5,关闭资源
class UdpRece
{
public static void main(String[] args)throws Exception
{
//1,创建udp socket,建立端点。
DatagramSocket ds = newDatagramSocket(10000);
while(true)
{
//2,定义数据包。用于存储数据。
byte[] buf = newbyte[1024];
DatagramPacket dp =new DatagramPacket(buf,buf.length);
//3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);//阻塞式方法。
//4,通过数据包的方法获取其中的数据。
String ip =dp.getAddress().getHostAddress();
String data = newString(dp.getData(),0,dp.getLength());
int port =dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
}
}
}
四、TCP编程
在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。而UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得。
这两种传输方式都是实际的网络编程中进行使用,重要的数据一般使用TCP方式进行数据传输,而大量的非核心数据则都通过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据的传递。
tcp分客户端和服务端:
1、客户端对应的对象是Socket。
客户端,通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
2、服务端对应的对象是ServerSocket。
服务端:
1,建立服务端的socket服务。ServerSocket();并监听一个端口。
2,获取连接过来的客户端对象。通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。
3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。并打印在控制台。
4,关闭服务端。(可选)
看下面小例子:
//客户端
class TcpClient
{
public static void main(String[] args)throws Exception
{
//创建客户端的socket服务。指定目的主机和端口
Socket s = newSocket("192.168.1.254",10003);
//为了发送数据,应该获取socket流中的输出流。
OutputStream out =s.getOutputStream();
out.write("tcp ge menlai le ".getBytes());
s.close();
}
}
//服务端
class TcpServer
{
public static void main(String[] args)throws Exception
{
//建立服务端socket服务。并监听一个端口。
ServerSocket ss = newServerSocket(10003);
//通过accept方法获取连接过来的客户端对象。
while(true)
{
Socket s =ss.accept();
String ip =s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
InputStream in =s.getInputStream();
byte[] buf = newbyte[1024];
int len =in.read(buf);
System.out.println(newString(buf,0,len));
s.close();//关闭客户端.
}
}
}