First, basic concepts
Before sharing BIO, let's figure out what is blocking/non-blocking and what is synchronous/non-synchronous.
1. Blocking/non-blocking: IO read blocking between the kernel (memory) and threads (applications in JVM).
2. Synchronization/asynchronization: When a thread requests kernel data (IO in this case), does it need to wait (before the kernel data is ready)? If so, it is synchronized and does not need to wait.
2. Synchronized blocking - BIO
Case: Create a service listener, listen to the request of the Servlet, and return the data you want to return.
Step: init () - > start () - > process
ServerSocket creates listeners and configures port 8080
private int port = 8080; private ServerSocket serverSocket; private Map<String, GServlet> servletMapping = new HashMap<String, GServlet>(); private Properties properties = new Properties();
//1. Configure the startup port, default 8080 Server Socket IP: localhost //2. Configure the Servlet written by web.xml to inherit HttpServlet // servlet-name // servlet-class // url-pattern //3. Read configuration, url-pattern and Servlet establish a mapping relationship // Map servletMapping private void init(){ //Load the web.xml file and initialize the ServletMapping object try { String WEB_INF = this.getClass().getResource("/").getPath(); System.out.println(WEB_INF); FileInputStream io= new FileInputStream(WEB_INF + "web.properties"); properties.load(io); for(Object object: properties.keySet()){ String key = object.toString(); if(key.endsWith(".url")){ String servletName = key.replaceAll("\\.url$", ""); String url = properties.getProperty(key); String className = properties.getProperty(servletName + ".className"); //Single instance, multithreading GServlet obj = (GServlet)Class.forName(className).newInstance(); servletMapping.put(url, obj); } } io.close(); }catch (Exception e){ e.printStackTrace(); } }
private void start(){ //Initialize, read web.properties init(); try{ serverSocket = new ServerSocket(this.port); System.out.println("GP Tomcat Started. The port to listen on is ___________." + this.port); //2. Waiting for user requests, using a dead loop to wait for user requests while (true){ Socket socket = serverSocket.accept(); //4. HTTP request, the data sent is string, regular string (HTTP protocol) process(socket); } }catch (Exception e){ e.printStackTrace(); } }
private void process(Socket client) throws Exception{ InputStream io = client.getInputStream(); OutputStream os = client.getOutputStream(); GRequest gRequest = new GRequest(io); GRespones gRespones = new GRespones(os); //5. Get the URL from the protocol content and instantiate the corresponding Servlet with reflection String url = gRequest.getUrl(); if(servletMapping.containsKey(url)){ //6. Call the service() method of the instantiated object to execute the specific logical doGet/doPost method servletMapping.get(url).service(gRequest,gRespones); }else{ gRespones.write("404 - Not Found"); } os.flush(); os.close(); os.close(); client.close(); }
public static void main(String[] args) { new GTomact().start(); }
Third, blocking principle
BIO is mainly stream-oriented, InputStream and OutputStream, read and write methods. Various streams are blocked, which means that when a thread calls read() or write(), the thread is blocked until some data is read or written completely. The thread can't do anything else in the meantime.
Java BIO stream-oriented means that one or more bytes are read from the stream at a time until all bytes are read, and they are not cached anywhere. In addition, it cannot move the data in the stream back and forth. If you need to move the data read from the stream back and forth, you need to cache it into a buffer first.