1、网络基础知识html
一、两台计算机要经过网络进行通讯,必须具有:java
1)惟一的标识(IP地址);编程
2)须要共同的语言(协议);数组
3)辨别不一样应用程序(端口号)。服务器
二、了解相关概念网络
1)IP地址:多线程
每台计算机的惟一标识,用来区分网络中的不一样主机,是两台主机进行网络通讯必不可少的。2)协议:socket
(1)TCP/IP协议:目前世界上应用最为普遍的协议。是以TCP和IP为基础的不一样层次上多个协议的集合。也称为:TCP/IP协议族 或者 TCP/IP协议栈。(TCP: Transmission Control Protocol -- 传输控制协议;IP :Internet Protocol -- 互联网协议)this
3)CP/IP模型(网络分层):url
(1)物理层(如网线、网线槽)
(2)数据链路层
(3)网络层
(4)传输层:TCP/IP协议
(5)应用层:HTTP超文本传输协议、FTP文件传输协议、SMTP简单邮件传送协议、Telnet远程登陆服务。
4)端口号:
(1)用于区分不一样的应用程序;
(2)端口号范围为0-65535,其中0-1023为系统所保留;
(3)IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通讯链路的终结点,是TCP和UDP的基础。
(4)经常使用端口号-- http: 80; ftp; 21; telnet; 23。
5)JAVA中得网络支持。针对网络通讯的不一样层次,Java提供的网络功能有四大类:
(1)InetAddress:用于标识网络上的硬件资源。(IP地址)
(2)URL:统一资源定位符---经过URL能够直接读取或写入网络上得数据。
(3)Sockets:使用TCP协议实现网络通讯的Socket相关的类。
(4)Datagram:使用UDP协议,将数据保存在数据报中,经过网络进行通讯。
1)InetAddress类没有构造方法,因此不能直接new出一个对象;但能够经过InetAddress类的静态方法得到InetAddress的对象:如
InetAddress.getLocalHost();
InetAddress.getByName();
2)类主要方法:
String - address.getHostName();
String - address.getHostAddress();
public static InetAddress getByName(String host) throws UnknownHostException
// 在给定主机名的状况下肯定主机的 IP 地址。主机名能够是机器名(如 "java.sun.com"),也能够是其 IP 地址的文本表示形式
3)InetAddress使用示例代码:
import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; /** * InetAddress类的基本使用 */ public class InetAddressDemo { public static void main(String[] args) throws UnknownHostException { /* * 获取本地主机信息 */ InetAddress address = InetAddress.getLocalHost(); System.out.println("主机名称" + address.getHostName()); System.out.println("IP地址:" + address.getHostAddress()); byte[] bytes = address.getAddress(); // 以获取字节数组的形式获取地址 System.out.println("本身数组形式的ip: " + Arrays.toString(bytes)); System.out.println(address);// 直接输出InetAddress对象 System.out.println(); /* * 根据机器名获取InetAddresss实例 */ InetAddress address2 = InetAddress.getByName("Moonlight"); System.out.println("计算机名:" + address2.getHostName()); System.out.println("IP地址:" + address2.getHostAddress()); System.out.println(); /* * 根据IP获取InetAddress实例 */ InetAddress address3 = InetAddress.getByName("192.168.1.102"); System.out.println("计算机名:" + address3.getHostName()); System.out.println("IP地址:" + address3.getHostAddress()); System.out.println(); /* * 获取其它地址 */ InetAddress address4 = InetAddress.getByName("baidu.com"); System.out.println("计算机名:" + address4.getHostName()); System.out.println("IP地址:" + address4.getHostAddress()); System.out.println(); } }
1)简介:
(1)URL(Uniform Resource Locator)统一资源定位符,表示Internet上某一资源的地址
(2)URL由两部分组成:协议名称和资源名称,中间用冒号隔开
(3)在java.net包中,提供了URL类来表示URL
2)使用URL读取网页内容
(1)经过URL对象的openStream()方法能够获得指定资源的输入流
(2)经过输入流能够读取、访问网络上的数据
3)URL类使用示例代码:
import java.net.MalformedURLException; import java.net.URL; /** * URL经常使用方法 */ public class URLDemo { public static void main(String[] args) throws MalformedURLException { // 建立URL实例 URL url = new URL("http://www.baidu.com"); URL url2 = new URL(url, "/index.html?uname=1#test"); // 在原有的URL资源上再建立URL实例,#后面表示锚点 System.out.println("协议" + url2.getProtocol()); System.out.println("主机" + url2.getHost()); // 若是未指定端口号,则使用默认的端口号,此时getPort()返回-1 System.out.println("端口" + url2.getPort()); System.out.println("文件路径" + url2.getPath()); System.out.println("文件名称:" + url2.getFile()); System.out.println("相对路径" + url2.getRef()); System.out.println("查询字符串" + url2.getQuery()); } }
一、Socket通讯模型
1)上图的通讯模型的顺序为:
(1)先创建服务端监听Soket,等待客户端请求。
(2)客户端建立socket,向服务端发送请求。
(3)服务端接收请求,并建立链接socket到此步骤时,服务端与客户端创建了链接。
(4)服务端和客户端开始通讯(InputStream、OutputStream)。
(5)最后关闭socket与相关资源。
二、Socket实现TCP编程通讯的实现步骤
1)服务端:
(1)建立ServerSocket对象,绑定监听端口
(2)经过accept()方法监听客户端的请求
(3)创建链接后,经过输入流读取客户端发送的请求信息
(4)经过输出流向客户端发送相应信息
(5)关闭相关资源
代码示例:
import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; /** * 服务端 * 基于TCP协议的Socket通讯 -- 单线程 */ public class TCPServer { public static void main(String[] args) { try { // 1.建立一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听 ServerSocket serverSocket = new ServerSocket(8888); // 2.调用accept()方法开始监听,等待客户端的链接 System.out.println("服务器即将启动,等待客户端的链接***"); Socket socket = serverSocket.accept(); // 3.获取输入流,并读取客户端信息 InputStream is = socket.getInputStream(); InputStreamReader irs = new InputStreamReader(is); BufferedReader br = new BufferedReader(irs); String info = null; while((info=br.readLine()) != null){ System.out.println("服务器接收到消息:" + info); } socket.shutdownInput();//关闭输入流 // 4.获取输出流,响应客户端请求 OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os);// 包装为打印流 pw.write("终于等到你!"); pw.flush(); // 5.关闭资源 pw.close(); os.close(); br.close(); irs.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2)客户端:
(1)建立Socket对象,指明须要链接的服务器的地址和端口号
(2)链接创建后,经过输出流向服务器端发送请求信息
(3)经过输入流获取服务器相应的信息
(4)关闭相关资源
代码示例:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; /** * 客户端 * 基于TCP协议的Socket通讯 */ public class TCPClient { public static void main(String[] args) { try { // 1.建立客户端Socket,指定服务器地址和端口 Socket socket = new Socket("localhost", 8888); // 2.获取输出流,向服务器端发送信息 OutputStream os = socket.getOutputStream();//字节输出流 PrintWriter pw = new PrintWriter(os); pw.write("客户端发信息来啦~~"); pw.flush(); socket.shutdownOutput();// 关闭输出流 // 3.获取输入流,并读取服务器端的响应信息 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String info = null; while((info=br.readLine()) != null){ System.out.println("客户端接收到信息:" + info); } // 4.关闭资源 br.close(); is.close(); pw.close(); os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
三、应用多线程来实现服务器与多客户端之间的通讯的基本基本步骤
(1)服务器端建立ServerSocket,循环调用accept()等待客户端链接
(2)客户端建立一个socket并请求和服务器端链接
(3)服务器端接收客户端请求,建立socket与该客户创建专线链接
(4)创建链接的两个socket在一个单独的线程上对话
(5)服务器端继续等待新的链接
代码示例:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /** * 服务端 * 基于TCP协议的Socket通讯 -- 多线程实现多客户的通讯 */ public class TCPServerMulConnection { public static void main(String[] args) { try { // 建立一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听 ServerSocket serverSocket = new ServerSocket(8888); // 调用accept()方法开始监听,等待客户端的链接 System.out.println("服务器即将启动,等待客户端的链接***"); Socket socket = null; int count = 0; // 记录客户端的链接 // 循环监听等待客户端的链接 while (true) { // 调用accept()方法开始监听,等待客户端的链接 socket = serverSocket.accept(); // 建立一个新的线程 ServerThreadHelper serverThread = new ServerThreadHelper(socket); //serverThread.setPriority(4); //可设置线程优先级(优先级默认为5,数字越小,优先级越低;未设置优先级可能致使运行时速度很是慢,可适当下降) // 启动线程 serverThread.start(); count++; // 统计客户端的数量 InetAddress address = socket.getInetAddress(); System.out.println("第 " + count + " 个客户端链接成功!此客户端的ip为:" + address.getHostAddress()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 服务器端线程处理类 */ class ServerThreadHelper extends Thread{ // 和本线程相关的socket Socket socket = null; public ServerThreadHelper(Socket socket){ this.socket = socket; } // 线程执行的操做,响应客户端请求 public void run(){ InputStream is = null; InputStreamReader irs = null; BufferedReader br = null; OutputStream os = null; PrintWriter pw = null; try { // 1.获取输入流,并读取客户端信息 is = socket.getInputStream(); irs = new InputStreamReader(is); br = new BufferedReader(irs); String info = null; while((info=br.readLine()) != null){ System.out.println("服务器接收到消息:" + info); } socket.shutdownInput();//关闭输入流 // 2.获取输出流,响应客户端请求 os = socket.getOutputStream(); pw = new PrintWriter(os); pw.write("终于等到你!"); pw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { // 3.关闭资源 try { if (pw!=null) { pw.close(); } if (os!=null) { os.close(); } if (br!=null) { br.close(); } if (irs!=null) { irs.close(); } if (is!=null) { is.close(); } if (socket!=null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
一、UDP编程简介
(1)UDP协议(用户数据报协议)是无链接、不可靠、无序的,特色是速度比较快
(2)进行数据传输时,首先要将要传输的数据定义成数据报(Datagram),在数据报中指明数据所要达到的Socket(主机地址和端口号),而后再将数据报发送出去
(3)相关的操做类:DatagramPacket:表示数据报包 DatagramSocket:进行端到端通讯的类
二、Socket实现UDP编程
1)服务器端实现步骤
(1)建立DatagramSocket,指定端口号
(2)建立DatagramPacket,用于接收客户端请求
(3)接收客户端发送的数据信息
(4)读取数据
(5)关闭资源
示例代码:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /** * 服务端 * 基于UDP实现Socket通讯 */ public class UDPServer { public static void main(String[] args) throws IOException { /* * 接收客户发送的数据 */ // 1.建立服务器端DatagramSocket,指定端口 DatagramSocket socket = new DatagramSocket(8800); // 2.建立数据报,用于接收客户端发送的数据 byte[] data = new byte[1024]; DatagramPacket packet = new DatagramPacket(data, data.length); // 3.接收客户端发送的数据 System.out.println("服务器已启动,等待接收数据报中……"); socket.receive(packet); // 此方法在接收到数据报以前会一直阻塞 // 4.读取数据 String info = new String(data, 0, packet.getLength()); System.out.println("服务器接收到了新信息:" + info); /* * 向客户端响应数据 */ // 1.定义 InetAddress address = packet.getAddress(); int port = packet.getPort(); byte[] data2 = "服务器已经收到信息啦~".getBytes(); // 2.建立数据报,包含响应的数据信息 DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); // 3.发送数据,返回給客户端 socket.send(packet2); // 4.关闭资源 socket.close(); } }
2)客户端实现步骤
(1)定义发送信息
(2)建立DatagramPacket,包含将要发送的信息
(3)建立DatagramSocket
(4)发送数据(经过DatagramSocket发送)
(5)关闭资源
示例代码:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; /** * 客户端 * 基于UDP实现Socket通讯 */ public class UDPClient { public static void main(String[] args) throws IOException { /* * 发送消息给服务端 */ // 1.定义服务器的地址、端口号、数据报 InetAddress address = InetAddress.getByName("localhost"); int port = 8800; byte[] data = "你好!我是客户端。".getBytes(); // 2.建立数据报,包含发送的数据信息 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); // 3.建立DatagramSocket对象 DatagramSocket socket = new DatagramSocket(); // 4.向服务器端发送数据报 socket.send(packet); /* * 接收服务端响应 */ // 1.建立数据报,用于接收服务器端响应的数据 byte[] data2 = new byte[1024]; DatagramPacket packet2 = new DatagramPacket(data2, data2.length); // 2.接收服务器响应的数据 socket.receive(packet2); // 3.读取数据 String reply = new String(data2, 0, packet2.getLength()); System.out.println("客户端接收到新信息:" + reply); // 4.关闭资源 } }
一、使用多线程编写网络程序时,能够将线程的优先级下降,线程的优先级默认是五,数字越小,优先级越低;未设置优先级可能致使运行时速度很是慢,可适当下降。
二、对于同一个socket,若是关闭了输出流,则与该输出流相关的socket也会被关闭,因此通常不用关闭流,直接关闭socet便可。
三、能够将一个对象序列化以后,经过流的方式在网络上传输
ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(User);
四、网络上传输文件,也是将文件转换为流,经过流的方式在网络上传输
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(new File("d://")));