网络编程 -java高级技术
网络通信的基本概念
/**目标:基本软件结构。通信一定是基于软件结构实现的:1.C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷,IDEA等软件。2.B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等、软件:博学谷、京东、淘宝。(开发中的重点,基于网页设计界面,界面效果可以更丰富: Java Web开发)两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的协议下,实现两台计算机的通信的技术。*/
public class NetDemo01 {}
网络通信的三要素
/**目标:网络通信的三要素。1.协议协议:计算机网络客户端与服务端通信必须事先约定和彼此遵守的通信规则。HTTP , FTP , TCP , UDP , SSH , SMTP。2.IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。IPv4:4个字节,32位组成。 192.168.70.70局域网城域网广域网(公网)局域网:公司内部用。公网:可以在任何地方访问。IPv6: 可以实现为所有设备分配IP 128位ipconfig:查看本机的IPping 检查本机与某个IP指定的机器是否联通,或者说是检测对方是否在线。ping 空格 IP地址ping 220.181.57.216ping www.baidu.com注意:特殊的IP地址: 本机IP地址.(不受环境的影响,任何时候都存在这两个ip,可以直接找本机!)127.0.0.1 == localhost。3.端口:端口号就可以唯一标识设备中的进程(应用程序)了端口号:用两个字节表示的整数,它的取值范围是0~65535。0~1023之间的端口号用于一些知名的网络服务和应用。普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。报出端口被占用异常!!利用`协议`+`IP地址`+`端口号` 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。*/
public class NetDemo02 {}
网络通信的分层和协议
/**目标:网络通信的分层和协议。网络通信协议:通信协议是对计算机必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。-------------------------------------------------------------------------------应用层 :应用程序(QQ,微信,浏览器),可能用到的协议(HTTP,FTP,SMTP) 通常程序员只需要关心这一层------------------------------------------------------------------------------传输层 :TCP/IP协议 - UDP协议 计算机网络工程师需要精通的协议,有些技术我们也需要精通这一层协议,-----------------------------------------------------------------网络层 :IP协议 封装自己的IP和对方的IP和端口-----------------------------------------------------------------数据链路层 : 进入到硬件(网)-----------------------------------------------------------------TCP/IP协议:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的安全的可靠的传输通信协议。1.在通信之前必须确定对方在线并且连接成功才可以通信。2.例如下载文件、浏览网页等(要求可靠传输)UDP:用户数据报协议(User Datagram Protocol)。UDP协议是一个面向无连接的不可靠传输的协议。1.直接发消息给对方,不管对方是否在线,发消息后也不需要确认。2.无线(视频会议,通话),性能好,可能丢失一些数据!!*/
public class NetDemo03 {}
import java.net.InetAddress;
import java.net.UnknownHostException;/**目标:InetAddress类概述一个该类的对象就代表一个IP地址对象。InetAddress类成员方法:static InetAddress getLocalHost()* 获得本地主机IP地址对象。static InetAddress getByName(String host)* 根据IP地址字符串或主机名获得对应的IP地址对象。String getHostName()* 获得主机名。String getHostAddress()* 获得IP地址字符串。*/
public class InetAddressDemo01 {public static void main(String[] args) throws Exception {// 1.获取本机地址对象。InetAddress ip = InetAddress.getLocalHost();System.out.println(ip.getHostName());System.out.println(ip.getHostAddress());// 2.获取域名ip对象InetAddress ip2 = InetAddress.getByName("www.baidu.com");System.out.println(ip2.getHostName());System.out.println(ip2.getHostAddress());// 3.获取公网IP对象。InetAddress ip3 = InetAddress.getByName("182.61.200.6");System.out.println(ip3.getHostName());System.out.println(ip3.getHostAddress());// 4.判断是否能通: ping 5s之前测试是否可通System.out.println(ip2.isReachable(5000)); // ping}
}
UDP通信的使用介绍(了解即可)
客户端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;/**目标:UDP通信的使用介绍(了解即可)UDP协议的特点* 面向无连接的协议* 发送端只管发送,不确认对方是否能收到。* 基于数据包进行数据传输。* 发送数据的包的大小限制64KB以内* 因为面向无连接,速度快,但是不可靠。会丢失数据!UDP协议的使用场景* 在线视频* 网络语音电话UDP协议相关的两个类* DatagramPacket* 数据包对象* 作用:用来封装要发送或要接收的数据,比如:集装箱* DatagramSocket* 发送对象* 作用:用来发送或接收数据包,比如:码头DatagramPacket类构造器发送端用:new DatagramPacket(byte[] buf, int length, InetAddress address, int port)创建发送端数据包对象* buf:要发送的内容,字节数组* length:要发送内容的长度,单位是字节* address:接收端的IP地址对象* port:接收端的端口号接收端用:new DatagramPacket(byte[] buf, int length)* 创建接收端的数据包对象* buf:用来存储接收到内容* length:能够接收内容的长度DatagramPacket类常用方法* int getLength() 获得实际接收到的字节个数DatagramSocket类构造方法* DatagramSocket() 创建发送端的Socket对象,系统会随机分配一个端口号。* DatagramSocket(int port) 创建接收端的Socket对象并指定端口号DatagramSocket类成员方法* void send(DatagramPacket dp) 发送数据包* void receive(DatagramPacket p) 接收数据包需求:使用UDP实现客户端发,服务端收。(了解)*/
public class UDPClientDemo01 {public static void main(String[] args) throws Exception {System.out.println("===启动客户端===");// 1.创建一个集装箱对象,用于封装需要发送的数据包!/**new DatagramPacket(byte[] buf, int length, InetAddress address, int port)参数一:封装数据的字节数组。参数二:发送数据的长度!参数三:服务端的IP地址参数四:服务端程序的端口号码。*/byte[] buffer = "今晚,约吗?".getBytes();DatagramPacket packet = new DatagramPacket(buffer , buffer.length, InetAddress.getLocalHost(),6666);// 2.创建一个码头对象// 参数可以申明客户端端口,可以有可以没有,默认会给一个端口。DatagramSocket socket = new DatagramSocket();// 3.开始发送数据包对象socket.send(packet);socket.close();}
}
服务端
import java.net.DatagramPacket;
import java.net.DatagramSocket;/*** 目标:UDP服务端开发。接收客户端的消息。*/
public class UDPServerDemo02 {public static void main(String[] args) throws Exception {System.out.println("==启动服务端程序==");// 1.创建一个接收客户都端的数据包对象(集装箱)/*** new DatagramPacket(byte[] buffer ,int lenght):* 参数一:接收数据的数组。* 参数二:接收数据的数组的长度!*/byte[] buffer = new byte[1024*64];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);// 2.创建一个接收端的码头对象DatagramSocket socket = new DatagramSocket(6666);// 3.开始接收socket.receive(packet);// 4.从集装箱中获取本次读取的数据量int len = packet.getLength();// 5.输出数据String rs = new String(buffer , 0 , len);System.out.println(rs);// 6.服务端还可以获取发来信息的客户端的IP和端口。String ip = packet.getAddress().getHostAddress();int port = packet.getPort();System.out.println("对方:"+ip+":"+port);socket.close();}
}
TCP通信
TCP可靠传输通信入门案例(非常重要)
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;/**目标:TCP可靠传输通信入门案例(非常重要)。TCP/IP协议 ==> Transfer Control Protocol ==> 传输控制协议TCP/IP协议的特点* 面向连接的协议* 只能由客户端主动发送数据给服务器端,服务器端接收到数据之后,可以给客户端响应数据。* 通过三次握手建立连接,连接成功形成数据传输通道。* 通过四次挥手断开连接* 基于IO流进行数据传输* 传输数据大小没有限制* 因为面向连接的协议,速度慢,但是是可靠的协议。TCP协议的使用场景* 文件上传和下载* 邮件发送和接收* 远程登录TCP协议相关的类* Socket* 一个该类的对象就代表一个客户端程序。* ServerSocket* 一个该类的对象就代表一个服务器端程序。TCP通信也叫Socket网络编程,只要代码基于Socket开发,底层就是基于了可靠传输的TCP通信。Socket类构造方法* Socket(String host, int port)* 根据ip地址字符串和端口号创建客户端Socket对象* 注意事项:只要执行该方法,就会立即连接指定的服务器程序,如果连接不成功,则会抛出异常。如果连接成功,则表示三次握手通过。Socket类常用方法* OutputStream getOutputStream(); 获得字节输出流对象* InputStream getInputStream();获得字节输入流对象客户端的开发流程:1.客户端要请求于服务端的socket管道连接。2.从socket通信管道中得到一个字节输出流3.通过字节输出流给服务端写出数据。服务端的开发流程:1.注册端口。2.接收客户端的Socket管道连接。3.从socket通信管道中得到一个字节输入流。4.从字节输入流中读取客户端发来的数据。需求:客户端发送一行数据,服务端接收一行数据!!小结:1.客户端用Socket连接服务端。2.服务端用ServerSocket注册端口,接收客户端的Socket连接。3.通信是很严格的,对方怎么发,你就应该怎么收,对方发多少你就只能收多少。4.实现的面向连接的socket端到端的通信管道,一方如果出现对象,另一方会出现异常!*/
public class ClientDemo01 {public static void main(String[] args) throws Exception {// 1.客户端要请求于服务端的socket管道连接。// Socket(String host, int port)Socket socket = new Socket("127.0.0.1" , 9999);// 2.从socket通信管道中得到一个字节输出流OutputStream os = socket.getOutputStream();// 3.把低级的字节输出流包装成高级的打印流。PrintStream ps = new PrintStream(os);// 4.开始发消息出去ps.println("我是客户端,喜欢你很久了,第一次给你发消息,只想说:约吗?");ps.flush();System.out.println("客户端发送完毕~~~~");}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/**目标:开发服务器。1.注册端口。2.接收客户端的Socket管道连接。3.从socket通信管道中得到一个字节输入流。4.从字节输入流中读取客户端发来的数据。ServerSocket类:构造器:public ServerSocket(int port)方法:public Socket accept():-- 等待接收一个客户端的Socket管道连接请求,连接成功返回一个Socket对象*/
public class ServerDemo02 {public static void main(String[] args) throws Exception {System.out.println("----服务端启动----");// 1.注册端口: public ServerSocket(int port)ServerSocket serverSocket = new ServerSocket(9999);// 2.开始等待接收客户端的Socket管道连接。Socket socket = serverSocket.accept();// 3.从socket通信管道中得到一个字节输入流。InputStream is = socket.getInputStream();// 4.把字节输入流转换成字符输入流Reader isr = new InputStreamReader(is);// 5.把字符输入流包装成缓冲字符输入流。BufferedReader br = new BufferedReader(isr);// 6.按照行读取消息 。String line ;if((line = br.readLine())!=null){System.out.println(line);}}
}
客户端可以反复发送数据,服务端可以反复数据
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;/**目标:客户端可以反复发送数据,服务端可以反复数据!!分析:只需要让客户端通过循环进行数据的发送。产生的问题:目前服务端只能接收一个客户端请求。*/
public class ClientDemo01 {public static void main(String[] args) throws Exception {// 1.客户端要请求于服务端的socket管道连接。// Socket(String host, int port)Socket socket = new Socket("127.0.0.1" , 9999);// 2.从socket通信管道中得到一个字节输出流OutputStream os = socket.getOutputStream();// 3.把低级的字节输出流包装成高级的打印流。PrintStream ps = new PrintStream(os);// 4.开始发消息出去while(true){Scanner sc = new Scanner(System.in);System.out.print("请说:");ps.println(sc.nextLine());ps.flush();}}
}
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;/**目标:开发服务器。1.注册端口。2.接收客户端的Socket管道连接。3.从socket通信管道中得到一个字节输入流。4.从字节输入流中读取客户端发来的数据。ServerSocket类:构造器:public ServerSocket(int port)方法:public Socket accept():-- 等待接收一个客户端的Socket管道连接请求,连接成功返回一个Socket对象*/
public class ServerDemo02 {public static void main(String[] args) throws Exception {System.out.println("----服务端启动----");// 1.注册端口: public ServerSocket(int port)ServerSocket serverSocket = new ServerSocket(9999);// 2.开始等待接收客户端的Socket管道连接。Socket socket = serverSocket.accept();// 3.从socket通信管道中得到一个字节输入流。InputStream is = socket.getInputStream();// 4.把字节输入流转换成字符输入流Reader isr = new InputStreamReader(is);// 5.把字符输入流包装成缓冲字符输入流。BufferedReader br = new BufferedReader(isr);// 6.按照行读取消息 。String line ;while((line = br.readLine())!=null){System.out.println(line);}}
}
实现一个服务端可以同时接收多个客户端的消息
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;/**目标:实现一个服务端可以同时接收多个客户端的消息。总结:需要在服务端引入多线程。每接收一个客户端的Socket通道,就为它分配一个独立的线程来处理它的消息。如此便可实现:一个服务端可以同时接收多个客户端的消息。*/
public class ClientDemo01 {public static void main(String[] args) throws Exception {// 1.客户端要请求于服务端的socket管道连接。// Socket(String host, int port)Socket socket = new Socket("127.0.0.1" , 9999);// 2.从socket通信管道中得到一个字节输出流OutputStream os = socket.getOutputStream();// 3.把低级的字节输出流包装成高级的打印流。PrintStream ps = new PrintStream(os);// 4.开始发消息出去while(true){Scanner sc = new Scanner(System.in);System.out.print("请说:");ps.println(sc.nextLine());ps.flush();}}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/**目标:开发服务器。1.注册端口。2.接收客户端的Socket管道连接。3.从socket通信管道中得到一个字节输入流。4.从字节输入流中读取客户端发来的数据。*/
public class ServerDemo02 {public static void main(String[] args) throws Exception {System.out.println("----服务端启动----");// 1.注册端口: public ServerSocket(int port)ServerSocket serverSocket = new ServerSocket(9999);// 2.定义一个循环不断的接收客户端的连接请求while(true){// 3.开始等待接收客户端的Socket管道连接。Socket socket = serverSocket.accept();// 4.每接收到一个客户端必须为这个客户端管道分配一个独立的线程来处理与之通信。new ServerReaderThread(socket).start();}}
}class ServerReaderThread extends Thread{private Socket socket ;public ServerReaderThread(Socket socket){this.socket = socket;}@Overridepublic void run() {try{// 3.从socket通信管道中得到一个字节输入流。InputStream is = socket.getInputStream();// 4.把字节输入流转换成字符输入流Reader isr = new InputStreamReader(is);// 5.把字符输入流包装成缓冲字符输入流。BufferedReader br = new BufferedReader(isr);// 6.按照行读取消息 。String line ;while((line = br.readLine())!=null){System.out.println(socket.getRemoteSocketAddress()+"说:"+line);}}catch (Exception e){System.out.println(socket.getRemoteSocketAddress()+"下线了~~~~~~");}}
}
使用线程池
import java.net.ServerSocket;
import java.net.Socket;// 放弃了1 客户端 一个线程的模型了
// 提供了线程池:
public class Server {public static void main(String[] args) {try {System.out.println("----------服务端启动成功------------");ServerSocket ss = new ServerSocket(9999);// 一个服务端只需要对应一个线程池HandlerSocketThreadPool handlerSocketThreadPool =new HandlerSocketThreadPool(3, 100);// 客户端可能有很多个while(true){Socket socket = ss.accept() ;System.out.println("有人上线了!!");// 每次收到一个客户端的socket请求,都需要为这个客户端分配一个// 独立的线程 专门负责对这个客户端的通信!!handlerSocketThreadPool.execute(new ReaderClientRunnable(socket));}} catch (Exception e) {e.printStackTrace();}}
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**拓展:(了解)引入:我们之前引入的线程解决一个服务端可以接收多个客户端消息客户端与服务端的线程模型是: N-N的关系。 一个客户端要一个线程。这种模型是不行的,并发越高,系统瘫痪的越快!!解决:我们可以在服务端引入线程池,使用线程池来处理与客户端的消息通信!!线程池不会引起出现过多的线程而导致系统死机!!这种方案的优劣势:优势:不会引起系统的死机,可以控制并发线程的数量。劣势:同时可以并发的线程将受到限制。*/
public class Client {public static void main(String[] args) {try {// 1.客户端要请求于服务端的socket管道连接。// Socket(String host, int port)Socket socket = new Socket("127.0.0.1" , 9999);// 2.从socket通信管道中得到一个字节输出流OutputStream os = socket.getOutputStream();// 3.把低级的字节输出流包装成高级的打印流。PrintStream ps = new PrintStream(os);Scanner sc = new Scanner(System.in);while(true){System.out.print("请说:");String msg = sc.nextLine();ps.println(msg);ps.flush();}} catch (Exception e) {e.printStackTrace();}}
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;// 线程池处理类
public class HandlerSocketThreadPool {// 线程池 private ExecutorService executor;// 线程池:3个线程 100个public HandlerSocketThreadPool(int maxPoolSize, int queueSize){executor = new ThreadPoolExecutor(maxPoolSize,maxPoolSize,120L, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(queueSize) );}public void execute(Runnable task){this.executor.execute(task);}
}
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.Socket;class ReaderClientRunnable implements Runnable {private Socket socket ;public ReaderClientRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 读取一行数据InputStream is = socket.getInputStream() ;// 转成一个缓冲字符流Reader fr = new InputStreamReader(is);BufferedReader br = new BufferedReader(fr);// 一行一行的读取数据String line = null ;while((line = br.readLine())!=null){ // 阻塞式的!!System.out.println("服务端收到了数据:"+line);}} catch (Exception e) {System.out.println("有人下线了");}}
}
文件上传
import java.io.*;
import java.net.Socket;/**目标:实现客户端上传图片给服务端保存起来。开发客户端:本地图片: D:\itcast\图片资源\beautiful.jpg开发服务端:服务器路径: D:\itcast\约吧图片服务器*/
public class ClientDemo {// 本地图片路径、public static void main(String[] args) throws Exception {// 1.请求于服务端的Socket管道连接。Socket socket = new Socket(Constants.SERVER_IP , Constants.SERVER_PORT);// 2.从socket管道中得到一个字节输出流包装成缓冲字节输出流BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());// 3.提取本机的图片上传给服务端// 4.得到一个缓冲字节输入流与本地图片接通BufferedInputStream bis =new BufferedInputStream(new FileInputStream(Constants.SRC_IMAGE));// 5.定义一个字节数组byte[] buffer = new byte[1024];int len ;while((len = bis.read(buffer)) != -1) {bos.write(buffer, 0 ,len);}bos.flush(); // 刷新图片数据到服务端!!socket.shutdownOutput(); // 告诉服务端我的数据已经发送完毕,请不要在等我了!bis.close(); // 可以关闭// 6.等待着服务端的响应数据!!BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println("收到服务端响应:"+br.readLine());}
}
/*** 客户端常量包*/
public class Constants {public static final String SRC_IMAGE = "D:\\itcast\\图片资源\\beautiful.jpg";public static final String SERVER_DIR = "D:\\itcast\\约吧图片服务器\\";public static final String SERVER_IP = "127.0.0.1";public static final int SERVER_PORT = 8888;}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;/**功能点:1.接收多个客户端传输来的图片数据存储到服务器路径:2.响应一个成功的消息给当前客户端。*/
public class ServerDemo {public static void main(String[] args) throws Exception {System.out.println("----服务端启动----");// 1.注册端口: public ServerSocket(int port)ServerSocket serverSocket = new ServerSocket(Constants.SERVER_PORT);// 2.定义一个循环不断的接收客户端的连接请求while(true){// 3.开始等待接收客户端的Socket管道连接。Socket socket = serverSocket.accept();// 4.每接收到一个客户端必须为这个客户端管道分配一个独立的线程来处理与之通信。new ServerReaderThread(socket).start();}}
}class ServerReaderThread extends Thread{private Socket socket ;public ServerReaderThread(Socket socket){this.socket = socket;}@Overridepublic void run() {try{// 1.从socket通信管道中得到一个字节输入流读取客户端发来的图片数据!InputStream is = socket.getInputStream();// 2.包装成高级的缓冲字节输入流BufferedInputStream bis = new BufferedInputStream(is);// 3.定义一个缓冲字节输出流通向目标路径(服务端路径)BufferedOutputStream bos =new BufferedOutputStream(new FileOutputStream(Constants.SERVER_DIR+ UUID.randomUUID().toString()+".jpg"));byte[] buffer = new byte[1024];int len ;while((len = bis.read(buffer)) != -1) {bos.write(buffer, 0 ,len);}bos.close();System.out.println("服务端接收完毕了!");// 4.响应数据给客户端PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("您好,已成功接收您上传的图片!");ps.flush();Thread.sleep(100000); // 等消失发送完毕被客户端接收后死亡!}catch (Exception e){System.out.println(socket.getRemoteSocketAddress()+"下线了~~~~~~");}}
}
B/S架构模拟
import com.itheima._07TCP通信四.Server;import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;/**目标:BS-浏览器-服务器基本了解。引入:之前客户端和服务端都需要自己开发。也就是CS架构。接下来模拟一下BS架构。客户端:浏览器。(无需开发)服务端:自己开发。需求:在浏览器中请求本程序,响应一个网页文字给浏览器显示。*/
public class BSserverDemo {public static void main(String[] args) {try {// 1.注册端口ServerSocket ss = new ServerSocket(8080);// 2.创建一个循环接收多个客户端的请求。while(true){Socket socket = ss.accept();// 3.交给一个独立的线程来处理!new ServerReaderThread(socket).start();}} catch (Exception e) {e.printStackTrace();}}
}class ServerReaderThread extends Thread{private Socket socket;public ServerReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 响应消息数据给浏览器显示。// 浏览器是基于HTTP协议通信!响应格式必须满足HTTP协议数据格式的要求,浏览器// 才能够识别,否则响应消息浏览器根本不认识。PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("HTTP/1.1 200 OK"); // 响应数据的响应头数据!ps.println("Content-Type:text/html;charset=UTF-8");//响应数据的类型。网页或者文本内容!ps.println(); // 必须换一行// 以下开始响应真实的数据!!ps.println("<span style='color:green;font-size:100px;'>牛逼的128期<span>");Thread.sleep(4000);ps.close();} catch (Exception e) {e.printStackTrace();}}
}
基本通信模型的概念介绍
/**拓展:基本通信模型的概念介绍。1.BIO通信模式:同步阻塞式通信。(Socket网络编程也就是上面的通信架构)-- 同步:当前线程要自己进行数据的读写操作。(自己去银行取钱)-- 异步: 当前线程可以去做其他事情,(委托一小弟拿银行卡到银行取钱,然后给你)-- 阻塞: 在数据没有的情况下,还是要继续等待着读。(排队等待)-- 非阻塞:在数据没有的情况下,会去做其他事情,一旦有了数据再来获取。(柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理)BIO表示同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。同步阻塞式性能极差:大量线程,大量阻塞。2.伪异步通信:引入了线程池。不需要一个客户端一个线程,可以实现1个线程复用来处理很多个客户端!这种架构,可以避免系统的死机,因为不会出现很多线程,线程可控。但是高并发下性能还是很差:a.线程数量少,数据依然是阻塞的。数据没有来线程还是要等待!3.NIO表示同步非阻塞IO,服务器实现模式为请求对应一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。1个主线程专门负责接收客户端:1个线程[c1 ,s2 ,c3,c4, ,s2 ,c3,c4,,c3,c4, ,s2 ,c3,c4]轮询所有的客户端,发来了数据才会开启线程处理这种架构性能还可以!!同步:线程还是要不断的接收客户端连接,以及处理数据。非阻塞:如果一个管道没有数据,不需要等待,可以轮询下一个管道是否有数据!4.AIO表示异步非阻塞IO,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由操作系统先完成IO操作后再通知服务器应用来启动线程进行处理。异步:服务端线程接收到了客户端管道以后就交给底层处理它的io通信。自己可以做其他事情。非阻塞:底层也是客户端有数据才会处理,有了数据以后处理好通知服务器应用来启动线程进行处理。小结:各种模型应用场景:BIO适用于连接数目比较小且固定的架构,该方式对服务器资源要求比较高,JDK 1.4以前的唯一选择。NIO适用于连接数目多且连接比较短(轻操作)的架构,如聊天服务器,编程复杂,JDK 1.4开始支持。AIO适用于连接数目多且连接比较长(重操作)的架构,如相册服务器,充分调用操作系统参与并发操作,编程复杂,JDK 1.7开始支持。*/
public class NioDemo {}
网络编程 -java高级技术相关推荐
- android xml java混合编程_Java学习中注解与多线程,网络编程与XML技术
本部分内容主要有集合框架及泛型,实用类,输入和输出处理,注解与多线程,网络编程与XML技术.初次学习这部分会感觉很难,主要是概念难于理解,最好是多看看例子,多练习.下面是个人的总结 拉勾IT课小编为大 ...
- Java高级技术梳理
java高级技术梳理 序言 内容 环境搭建 高级技术 maven技术 zookeeper技术 Dobbo技术 vsftpd技术 nginx技术 Redis技术 solr技术 ActiveMq技术 Js ...
- Java高级技术笔记
Java高级技术笔记 URL地址 HTTP协议 开发工具 Java开发工具包(JDK) JSP引擎 MyEclipse IDEA 工具集成 C/S架构是Client/Server的简写,也就是客户机/ ...
- 网络编程-java入门
网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编程是比较复 ...
- java获取主机信息大全,网络编程:Java获取网络主机信息
java.net.InetAddress类表示互联网协议 (IP) 地址. 有两个子类:Inet4Address, Inet6Address 通过 InetAddress可以方便获取一个域名下的IP, ...
- 网络编程--JAVA之多线程下载后续:断点续存
这篇博客就是接在我上篇博客网络编程–JAVA之多线程下载的基础上来实现的. 首先,我来说一下断点续存能解决啥问题: 假如当我们在进行MP4下载时,如果突然出现人为的中断或者意外的中断,那么当我们再次点 ...
- Unix网络编程(六)高级I/O技术之复用技术 select
转载:http://blog.csdn.net/michael_kong_nju/article/details/44887411 I/O复用技术 本文将讨论网络编程中的高级I/O复用技术,将从下面几 ...
- 计算机tcpip网络原理与应用,清华大学出版社-图书详情-《TCP/IP网络编程原理与技术》...
前言 随着Internet的发展,网络技术已经渗透到人们的生活和工作中.TCP/IP已经成为最流行的网络协议,且还在演变以满足未来的需要.在速度越来越快的计算机硬件和不断更新的软件发展的背后,TCP/ ...
- php面试题之三——PHP网络编程(高级部分)
三.PHP网络编程 [!!!]1.禁用COOKIE后SEESION还能用吗?(51.com笔试题) 可以,COOKIE和SESSION都是用来实现会话机制的,由于http协议是无状态的,所以要想跟踪一 ...
最新文章
- 银行使用oracle做查询,Oracle EBS ERP银行信息查询视图
- 为什么人工智能被过度炒作?
- 机器学习基础专题:高斯判别分析
- TCP/IP协议:概述
- MYECLIPSE中快速解决项目的错误的方法
- apache.camel_Apache Camel 2.9发布–十大变化
- 11月8日PHP练习《留言板》
- Linux 7.x 防火墙端口
- 自己定义AlertDialog对话框布局
- mysql中设置字符,MySQL 修改默认字符集
- Winform的html编辑控件htmleditor 有时候无法为里面HTML属性初始化
- md文件 markdown打开工具(typora)
- 用yum下载安装gcc
- python音标1003python音标_词汇小助手V1.2——可以显示英语单词的国际音标
- 怎么把php转成bt_php能不能转换成bt种子
- 鸿蒙与混沌的区别,混沌的近义词(混沌鸿蒙同义词)
- unity text颜色渐变
- 水文勘测工比赛计算机基本应用,水文勘测工技能大赛参赛感言
- python求平均工资_python实现求和,求平均值——函数
- 【Docker】Docker安装
热门文章
- ipad2 越狱后安装slide enhancer 隐藏滑块解决方法总结
- 7-1 公路村村通(prim)
- 蚁狮优化算法( Ant Lion Optimizer,ALO)-Matlab源码
- Streams AQ: qmn coordinator waiting for slave to start
- 统一通信概念鱼龙混杂
- 华为路由器AR2200-S调试限速
- 再回首 --- 零点伤感
- 学计算机学不会怎么办,怎样学习计算机编程
- 运行mybatis时显示报错:Error updating database. Cause: java.sql.SQLException: Error setting driver on
- python编写程序 计算1_《Python程序设计》——第1章 计算与问题求解简介 1.1 计算与Python简介-阿里云开发者社区...