本章概述:
第一部分:网络编程
第二部分:UDP
第三部分:TCP
第四部分:URL
第一部分:网络编程
1、概述:
网络编程的的作用是实现两个设备之间的数据交换。
数据交互,就是把一个设备中的数据发送给另外的设备,然后接受设备反馈的信息。
现在的网络编程基本上都是基于请求/响应方式的,也就是一个设备发送请求数据给另外一个,然后接收另一个设备的反馈。
在网络编程中,发起连接程序,也就是发送第一次请求的程序,被称作客户端(Client),等待其他程序连接的程序被称作服务器(Server)。
客户端程序可以在需要的时候启动,而服务器为了能够时刻响应连接,则需要一直启动。
2、网络通讯要素
1、IP地址:InetAddress
2、端口号IP地址是网络中设备的标识,对应一个主机名,主机名更易记忆
本地回环IP:127.0.0.1 , 可用于测试网卡等设备是否正常工作
地址段最后一段为255的表示是广播地址,可以在该地址段发送广播消息
数据要发送到对方的指定应用程序上,通过虚拟端口数字标识(逻辑端口),范围0~65535,0~1024通常是系统预留
3、传输协议:
定义通讯的规则,这个规则称为协议
国际通用协议:TCP/IP
3、网络模型
OSI参考模型
物理层
数据链路层
网络层
传输层
会话层
表示层
应用层
(数据拆封包)
TCP/IP参考模型
主机至网络层(物理层、数据链路)
网际层(IP)
传输层(UDP、TCP)
应用层(会话、表示、应用)(HTTP)
4、操作类
InetAddress
方法
getLoalHost 获取本地主机地址
toString
getHostAddress 获取IP地址字符串
getHostName 获取主机名
InetAddress.getByName(主机名) 获取主机地址
getAllByName 获取主机地址数组
Socket
为网络服务提供的一种机制
通讯的两端都有Socket
数据在两个端口间进行IO传输
第二部分:UDP
1、DatagramSocket
方法
send(DatagramPacket) 发送数据包
receive(DatagramPacket) 将接收的数据封装在指定数据包中
2、DatagramPacket
构造
DatagramPacket(字节数组,数据长度,地址,端口)
方法
getData 返回数据
建立
(1)建立UDPSocket服务(接收端需要明确监听一个端口)
(2)提供数据,封装成数据包
(3)发送数据包
(4)关闭资源
代码示例:
/* 需求:通过udp传输方式,将一个网络端的键盘录入传输到另一个网络应用 一、定义一个udp发送端。 思路: 1,建立udpsocket服务。 2,提供数据,并将数据和接收方的网络地址、端口封装到数据包中。 3,通过socket服务的发送功能,将数据包发出去。 4,关闭资源。 其实这就像我们生活中的发送包裹的例子 */ import java.net.*; import java.io.*; //定义一个数据发送端 class UDPSend { public static void main(String[] args) throws Exception { InetAddress ip = InetAddress.getLocalHost(); System.out.println(ip); //创建udpsocket,建立端点。 DatagramSocket ds = new DatagramSocket(); //创建键盘录入的流 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //循环读取键盘录入的数据,并封包发送 String line = null; while((line = bufr.readLine())!=null) { if("over".equals(line)) //键盘录入“over”则退出循环 break; byte[] buf = line.getBytes(); //将数据和要发送的地址以及指定的该主机的端口封装到数据包中 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("172.27.35.14"),10010); //将数据发送出去 ds.send(dp); } //退出循环后关闭流资源,程序结束 ds.close(); } } /* 二、定义ufp的接收端。 思路: 1,定义udpsocket服务,监听一个端口(其实就是给接收网络的应用程序定义数字标识,方便于明确哪些数据过来该应用程序可以处理)。 2,定义一个数据包,用于存储接收到的字节数据。 因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。 3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。 4,通过数据包对象的方法,将数据取出。打印在控制台上。 5,关闭资源。 */ //提示:因为UDP协议是面向无连接的,接收端如果不先监听端口,数据就会丢失,所以在开启发送端发送消息之前接收端要先开启并监听端口 //定义一个数据接收端 class UDPRece { public static void main(String[] args) throws Exception { //建立端点,监听端口 DatagramSocket ds = new DatagramSocket(10010); while(true) //循环接收发送端发过来的数据 { //建立数据包 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,0,buf.length); //接收从端口中发过来的数据,没接收到时,该数据一直阻塞 ds.receive(dp); //将包中封装的同时接收到的发送端的地址等信息展示出来 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); //String data = new String(dp.getData()); //不限定数据宽度就全部获取 //展示接收到的信息 System.out.println(ip+"..."+data); } //数据接收端应该一直开启以监听数据 ds.close(); } }
第三部分:TCP
1、Socket
客户端端口
构造时就可以指定连接的主机和端口
方法
getInputStream 获取与端口关联的输入流
getOutputStream 获取关联的输出流
shutdownOutput 传输数据结束标识
2、ServerSocket
服务端对象
构造时指定监听的端口
构造时可以指定同时访问的客户端数量
获取客户端的流
方法
getInputStream 获取的流的源是网络数据
getOutputSteam
accept 接收一个客户端对象
getInetAddress.getHostAddress
并发传输数据
无限循环开启线程获取客户端传输
代码示例:
/* 需求:用TCP协议各编写一个客户端和服务端,实现服务端将客户端发来的文本转换成大写返回,并且服务端支持并发访问 思路: 建立服务端: 1、建立服务端ServerSocket 2、获取一个客户端对象,将客户端对象传递到一个新线程中执行,服务端循环做上述动作 3、创建一个Runnable子类,构造函数传递客户端对象 4、客户端对象在run方法中读取客户端发来的消息,并将处理后的消息返回客户端,用到IO流技术 5、客户端发来停止请求信号,关闭客户端对象的资源,该线程结束 客户端: 1、建立客户端对象 2、获取关联的流,获取键盘录入 3、向服务端发送消息 4、接收服务端的消息并使用 5、用户录入“over”,退出交互,关闭流资源,退出程序 */ //用到IO流和net网络编程类 import java.io.*; import java.net.*; //服务端程序 class TCPServer { public static void main(String[] args) throws IOException { //创建服务端对象,监听端口“10086” ServerSocket ss = new ServerSocket(10086); //循环将接收到的客户端对象放到新的线程中执行 while (true) { Socket s = ss.accept(); new Thread(new ServerThread(s)).start(); } //服务端端通常一直开启,可以不用写关闭 //ss.close(); } } //定义用于激活线程的类,实现Runnable接口 class ServerThread implements Runnable { //定义Socket成员,并在构造函数中初始化 Socket s ; ServerThread(Socket s) { this.s = s; } //线程run方法 public void run() { try { //创建读取流和写入流,用与Socket中的方法获取与Socket关联的输入输出流 BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); //printStream类的对象有很多可以原样操作数据的方法,用起来很方便,但要记得刷新流(可以初始化时参数固定刷新) PrintStream out = new PrintStream(s.getOutputStream(),true); //获取连接到服务端的客户端ip并展示 String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connet..."); //循环接收和处理客户端的数据 String line = null; while ((line = in.readLine())!=null) { if ("over".equals(line.toLowerCase())) { break; //这里用不区分大小写的“over”来作为结束服务的标记消息 } out.println(line.toUpperCase()); //数据转成大写后返回 } } //简单处理异常和关闭客户端的流 catch (IOException e) { e.printStackTrace(); } finally { try { s.close(); } catch (IOException e) { e.printStackTrace(); } } } } //客户端程序 class TCPClient { public static void main(String[] args) { Socket s; try { //创建客户端对象,明确服务端Ip地址和端口 s = new Socket("172.27.35.14",10086); //分别创建一个接收和发送服务端消息以及获取键盘录入的流 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintStream out = new PrintStream(s.getOutputStream(),true); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); //循环发送和接收服务端消息,建立网络互访 String line = null; while ((line = bufr.readLine())!=null ) { out.println(line); //发送消息到服务端 if ("over".equals(line.toLowerCase())) { break; //退出交互信号 } //展示服务端返回的消息 System.out.println("服务端返回:"+in.readLine()); } } //处理异常和关闭客户端的流 catch (IOException e) { e.printStackTrace(); } finally { try { if(s!=null) s.close(); } catch (IOException e) { e.printStackTrace(); } } } }
3、UDP和TCP比较
UDP
面向无连接的网络连接协议
数据大小限制在64k内
因为是无连接,是不可靠协议
不需要连接,速度快
TCP
建立连接,形成数据传输通道
在连接中进行大数据传输
通过三次握手完成连接,是可靠协议
必须建立连接,速度稍慢
第四部分:URL
统一资源定位符
构造
URL(URL地址)
方法
getProtocol 获取地址
getHost
getPort
getPath
getFile 获取文件名(带参数)
getQuery 获取参数
openConnetion 获取一个与此对象相关联的端口连接对象
其实就是Connetion类内部就是封装了Socket对象并对Socket的常用实现功能进行了封装,使之更简单易用
方法
getInputStream
getOutputStream 这两方法和Socket类中的getInputStream的方法用法一样
openStream 是openConnetion.getStream的缩写
HTTP
请求消息头:以HTTP协议规范发送的请求消息
应答消息头:服务端返回数据的标识信息
代码示例:
import java.io.*; import java.net.*; class URLDemo { public static void main(String[] args) throws MalformedURLException,IOException { //创建一个URL对象,初始化一个地址 URL url = new URL("http://172.27.35.14:8080/myweb/demo.html?name=haha&age=30"); //URL的一些获取信息的方法 System.out.println("getProtocol():"+url.getProtocol()); //获取协议名称 System.out.println("getPort():"+url.getPort()); //获取URL封装的端口号 System.out.println("getPath():"+url.getPath()); //获取URL封装地址的路径部分 System.out.println("getFile():"+url.getFile()); //获取URL对应的文件名 System.out.println("getQuery():"+url.getQuery()); //获取URL的查询部分 //获取一个URLConnection连接对象(此对象可用于读取和写入此URL引用的资源) URLConnection conn = url.openConnection(); System.out.println(conn); //获取此连接打开的输入流 InputStream in = conn.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); //将输入流中的数据读取并打印 System.out.println(new String(buf,0,len)); } }
本章总结:
1、网络编程实现设备与设备间进行数据交互的功能。
2、网络编程的三要素:IP地址、端口号、传输协议,为网络间的数据传输定义了规则。
3、网络参考模型:有OSI模型和TCP/IP模型,主要描述通过网络传输数据的封包和传送过程。
4、UDP是一种面向无连接的网络通讯协议,主要特点是设备间不需要建立连接,快,但数据包有大小限制、会丢失,不安全;实现该协议的数据发送和接收都可以通过DatagramSocket的对象发送和接收DatagramPacket数据包来实现。
5、TCP是面向连接的网络通讯协议,主要特点是设备间要通过“三次握手”来实现建立数据通道传输数据,速度稍慢,安全;TCP连接分客户端和服务端,客户端通过Socket类创建连接端口,服务端通过ServerSocket类创建连接端口,开启客户端前需要先开启服务端,否则会连接失败。
6、URL类是封装了连接资源的类,可以使开发者跳过传输层直接在应用层建立网络连接,提高开发效率。