1、计算机网络计算机网络,是指将地理位置不同的具有独立功能的多台计算 机及其外部设备,通过通信线路连接起来,从而实现信息与资 源共享的计算机系统。
2、网络七成结构
3、网络通信协议
网络通讯协议计算机网络中的计算机可以相互间进行信息交流。而要进行交 流,就需要具有一定的规则,我们称之为通讯协议。可以认为, 协议就是一种规范。
相关协议: HTTP( HyperText Transfer Protocol )超文本传输协议 IP( Internet Protocol)互联网协议 TCP( Transmission Control Protocol)传输控制协议 UDP( User Datagram Protocol)用户数据报协议 FTP( File Transfer Protocol)文件传输协议
4、TCP/IP协议经常放在一起使用。在TCP/IP协议下,网络通常也 分成如下四层的结构:
5、TCP与UDP TCP协议是基于连接的协议,该协议提供点对点的通道,在 两台计算机设备间进行可靠的数据传输。 TCP协议保证一方 发送的数据可以准确的被另一方接收,并且接收数据的顺序 与发送的顺序一致。( HTTP, FTP) UDP协议是基于数据报的协议(不是基于连接的协议),该 协议发送独立的数据报(数据包),各个数据报之间不受影 响。 UDP协议不保证接收端一定会接收到发送端发送的数据 报,同时,也不保证接收数据报
的顺序与发送的顺序一致。 ( ping)
6、IP地址在计算机网络中,可能会存在多台计算机,我们使用IP地址来区分 每台计算机。可以认为, IP地址就是每台计算机在计算机网络中的 唯一标识。 IP地址使用32位数据来表示。我们习惯上将IP地址分为 4段,每段8位。( 0~255)
7、端口号 端口号用来标识不同的程序。端口号使用16位数据来表示。 ( 0~65535)其中, 0~1023端口被常用的系统服务所占用。我 们使用的服务不应使用这些端口。
说明:数据传输时,会携带IP地址与端口号信息。其中, IP地址用 来识别数据传输到哪台计算机,而端口号用来识别,传输到计算 机的哪个应用程序。
8、URLURL( Uniform Resource Locator)统一资源定位,为一个字符 串序列,引用网络上的一个资源地址,该地址可以是文件,目 录,数据库查询等。URL分为两个部分:(二者使用://进行分隔) 协议标识符 使用哪种协议获取相关资源 资源名称 资源的详细地址
例如: http://www.somewebsite.com
资源名称的格式取决于所使用的协议,大部分协议的格式如下: 主机名称 文件名称(路径) 端口号 相关引用
例如: http://127.0.0.1:8080/index.html#bak说明:通常主机名称与文件名称是必须的,而端口号与相关引 用是可选的。
在Java程序中,使用URL类可以创建一个URL。绝对URL: URL url = new URL("http://www.google.com");相对URL: URL url1 = new URL(“http://www.my.com/loc/”);URL url2 = new URL(url1, “file.zip”);说明: URL是非可变类。
package day19;import java.net.MalformedURLException;import java.net.URL;public class URLMethod { public static void main(String[] args) { try { URL url = new URL("http://127.0.0.1:8800/abc/123.txt?a=1&b=2#bak"); // 返回url的协议。 System.out.println(url.getProtocol()); // 返回主机。 System.out.println(url.getHost()); // 返回端口号。 System.out.println(url.getPort()); // 返回协议默认的端口号。 System.out.println(url.getDefaultPort()); // 返回文件(路径) System.out.println(url.getPath()); // 返回查询参数 System.out.println(url.getQuery()); // 返回文件路径(包含查询参数) System.out.println(url.getFile()); // 返回引用 System.out.println(url.getRef()); } catch (MalformedURLException e) { e.printStackTrace(); } }}
9、案例:通过URL下载文件与操作本地文件。
package day19;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;public class URLTest { public static void main(String[] args) { try { URL url = new URL("http://www.baidu.com"); // 返回输入流,可以读取url所定位的资源。 InputStream in = url.openStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String s; while ((s = br.readLine()) != null) { System.out.println(s); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URL;public class Download { public static void main(String[] args) { URL url = null; try { url = new URL("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"); } catch (MalformedURLException e1) { e1.printStackTrace(); } try (InputStream in = url.openStream(); OutputStream out = new FileOutputStream("c:/copy.png");) { int b; while ((b = in.read()) != -1) { out.write(b); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URL;public class LocalFile { public static void main(String[] args) { OutputStream out = null; try { URL url = new URL("file:///c:/copy.png"); InputStream in = url.openStream(); out = new FileOutputStream("c:/copy2.png"); int b; while ((b = in.read()) != -1) { out.write(b); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }}
10、URLConnection当创建URL对象后,就可以通过URL对象的openConnection方 法打开连接,该方法返回一个URLConnection对象。通过调用 URLConnection对象的connect方法与远程指定的资源建立通讯连接。
说明:通常,我们不需要显式调用connect方法打开连接,当执行特定的输入输出操作时(例如getInputStream ),连接会自动打开。
从URL中读取数据通过URLConnection类的getInputStream方法可以获得指定URL的输入流,该方法返回一个InputStream对象。说明:也可以直接通过URL对象的openStream方法直接获得指定资源的输入流。
向URL中写入数据通过URLConnection类的getOutputStream方法可以获得指定URL的输出流,该方法返回一个OutputStream对象。通过输出流对象,我们就可以向服务端写入数据。说明:客户端的输入流就是服务端的输出流,客户端的输出流就是服务端的输入流。
package day19;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;public class URLConnectionTest { public static void main(String[] args) { try { URL url = new URL("http://www.baidu.com"); // 获得URL连接的对象。获得连接对象不代表已经进行了 // 真正的连接。 URLConnection con = url.openConnection(); // 设置是否可以进行读取资源,默认为true。 con.setDoInput(true); // 设置是否可以进行写入资源。默认为false。 // 如果我们需要想URL资源写入数据,则需要 // 设置为true。 con.setDoOutput(true); // setDoInput与setDoOutput需要在连接之间 // 进行设置。(connect之前) // con.connect(); // 连接URL指定(定位)的资源。当进行获取输入流, // 输出流操作时,会自动进行连接(如果该连接尚未 // 打开)。 con.connect(); InputStream in = con.getInputStream(); // url.openStream(); // 后续的操作与之前相同 // 获取URL连接(URLConenction)的输出流。 OutputStream out = con.getOutputStream(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.nio.charset.Charset;public class URLWrite { public static void main(String[] args) { try { // 获得平台使用的编码 // System.out.println(System.getProperty("file.encoding")); // System.out.println(Charset.defaultCharset()); URL url = new URL("http://127.0.0.1/req"); URLConnection con = url.openConnection(); con.setDoOutput(true); // 使用转换流改变编码 PrintWriter pw = new PrintWriter(new OutputStreamWriter(con.getOutputStream(), "UTF-8"), true); pw.println("客户端的请求"); // pw.println("client request"); BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); String rtn = br.readLine(); // System.out.println("服务端的回应:" + rtn); System.out.println(rtn); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
11、Socket 网络上的两个程序建立双向的通讯连接,这个连接的一端称为一个socket,每个socket会绑定一个特定的端口号。客户端与服务端通过Socket进行数据读取与写入。 在Java中,使用Socket与ServerSocket类来实现数据的读取与写入。说明:相对于URL, Socket是更低层的操作。当连接web时,应该优先使用URL相关类来实现。
案例:通过Socket与ServerSocket实现客户端与服务端的通讯( TCP)。
package day19;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.Scanner;public class Server { public static void main(String[] args) { try { // 监听指定的端口号 ServerSocket server = new ServerSocket(8888); // 用来接收客户端的请求。该方法在客户端请求到来前 // 会处于阻塞状态。 Socket socket = server.accept(); new Read(socket).start(); new Write(socket).start(); } catch (IOException e) { e.printStackTrace(); } }}class Read extends Thread { private Socket socket; public Read(Socket socket) { this.socket = socket; } @Override public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String s; while ((s = br.readLine()) != null) { System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } }}class Write extends Thread { private Socket socket; public Write(Socket socket) { this.socket = socket; } @Override public void run() { try { PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { pw.println(scanner.nextLine()); } } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;import java.util.Scanner;public class Client { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 8888); new Read(socket).start(); new Write(socket).start(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
12、数据报 数据报是相互独立的信息,通过网络发送。对于接收端,是否能接收,接收时间,接收的顺序都是不确定的。 在Java中,使用DatagramSocket类来发送与接收数据报。使用DatagramPacket类表示数据报(数据报包)。
案例:通过DatagramSocket与DatagramPacket实现客户端与服务端的通讯。( UDP)
package day19;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;public class UServer { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(8888); byte[] data = new byte[100]; DatagramPacket dp = new DatagramPacket(data, data.length); // 接收客户端发送的数据报(数据包)。 // 该方法在接受数据报之前会一直处于阻塞状态。 ds.receive(dp); // 获得接受的数据 // dp.getData(); // 获得数据的长度。 // dp.getLength(); // 获得发送方的IP // dp.getAddress(); // 获得发送方的端口号。 // dp.getPort(); System.out.println(new String(dp.getData(), 0, dp.getLength())); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;public class UClient { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(); byte[] b = "你好".getBytes(); InetAddress ip = InetAddress.getByName("127.0.0.1"); DatagramPacket dp = new DatagramPacket(b, b.length, ip, 8888); // 发送数据报 ds.send(dp); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
13、广播使用MulticastSocket类实现广播功能。案例:多客户端发送案例。
package day19;import java.io.IOException;import java.net.DatagramPacket;import java.net.InetAddress;import java.net.MulticastSocket;public class Receiver { public static void main(String[] args) { try { MulticastSocket ms = new MulticastSocket(8888); InetAddress ip = InetAddress.getByName("224.0.0.1"); // 加入到指定的波段,就可以接收这个波段的广播。 ms.joinGroup(ip); while (true) { byte[] data = new byte[100]; DatagramPacket dp = new DatagramPacket(data, data.length); ms.receive(dp); System.out.println(new String(dp.getData(), 0, dp.getLength())); } // 离开指定的广播组。 // ms.leaveGroup(ip); } catch (IOException e) { e.printStackTrace(); } }}
package day19;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;import java.util.Random;public class Sender { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(); // 广播的波段,范围限制为224.0.0.0到239.255.255.255, // 其中224.0.0.0被保留,不能使用。 InetAddress ip = InetAddress.getByName("224.0.0.1"); while (true) { byte[] data = getData(); DatagramPacket dp = new DatagramPacket(data, data.length, ip, 8888); ds.send(dp); Thread.sleep(1000); } } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public static byte[] getData() { StringBuilder b = new StringBuilder(); Random r = new Random(); for (int i = 0; i < 10; i++) { int x = 65 + r.nextInt(26); b.append((char) x); } System.out.println(b); return b.toString().getBytes(); }}