The BIO initial network programming, NIO

       Prior to speak about the interview you may be asked of the three-way handshake with the four waving?

       A transmitting to B is assumed urban city letters sent to B to A, B is received, the issue A, B in A distributed, establish initial communications. Three wave is to prove A, receiving and transmission capability of B is ok, thus proved connection is normal.

        The first handshake: When A sends to B, B receives the letter, this time to understand the city B, the transmission capacity and receiving capacity B city A city is ok.

        Second handshake: When B is sent to A, the A received a letter, then the city A will understand, the transmission capacity and receiving capacity of the city A City B is ok, plus the previous transmission, while also know a (own) signaling capability and capacity of the receiving B city is ok, which is equivalent to a knows both sides are OK, but B also puzzled, because although it is the first time that the a the signaling capability of receiving one's own ability is OK, but do not know how to not receiving ability Town B (itself) of the signaling capability and a city, so need a third handshake.

        Third handshake: A receipt issued to B when B, you know B (its signaling capability) and receiver capabilities A city is also ok, since both sides know too much, it Taoxintaofei hi end even the rationale for it. Complete the establishment of the first communication.

       Probably flow seen in the following figure:

TCP three-way handshake protocol Once connected, it can be concluded
First handshake A -> B A concluded: what is not know, not sure if I send ok 
B concludes: A fat B close ok 
Second handshake B -> A A conclusion can be drawn: A hair collection B, plus the introduction of the first transmission may send A B before income also ok, so I can understand sending and receiving are ok AB
B concluded: The first time that B based on A hair close ok , but it does not know whether to send their own ability to accept success and a
Third handshake A -> B A sent B, after B receives the message can be proved: self-ok signaling capability and capacity of receiving A and B

In fact, this had to do before I was involved in a module, was in charge of writing a log download function, its implementation is the use of B / S structure to complete, that is, in such a combination of multi-threading to accomplish the use of socket programming Features. Device as a server (log sources), the browser as a client (retransmission request) to form a communication, since the InputStream class read () method is blocked, so it is necessary to use the multi-threaded, or thread pool, one request every hair on use a new thread thus interfere with each other, here is a little demo I analog (like chat) above operations.

Client code:

package NIO.clientpkg;

import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Scanner;


/**
 *目的:客户端向服务端发送请求服务端接受请求,并回应相同的信息,一旦客户端写入bye,则结束本次操作
 */
public class Client {


    public static void main(String[] args) throws Exception{
        SocketAddress socketAddress = new InetSocketAddress ("localhost",9001);
        Socket socket = new Socket ();
        socket.connect (socketAddress,1000*5);//5second
        //发送输入的数据  以打印流的方式
        PrintStream out = new PrintStream (socket.getOutputStream ());
        //接受服务端传来的数据,将其保存在打印流中
        Scanner in = new Scanner (socket.getInputStream ());
        System.out.println ("请输入你要发送给服务端的信息");
        Scanner scanner = new Scanner (System.in);
        while (true){
            //发送消息
            if (scanner.hasNext ()){ //hasNext和next都是半阻塞的方法,会一直处于等待,所以必须用一个变量来接收
                //输入的消息
                String str = scanner.next ();
                out.println (str);
                if (str.equals ("bye")){
                    System.out.println ("服务端发过来的消息:" + in.next ());
                    break;//不能立即退出,会导致客户端退出服务端还处于连接丢包
                }
                //接收消息
                if (in.hasNext ()){
                    System.out.println ("服务端发过来的消息:" + in.next ());
                }
            }
        }
        socket.close ();
        scanner.close ();
        in.close ();
        out.close ();
    }

}

Server code:

package NIO.serverpkg;

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 /**
 *目的:客户端向服务端发送请求服务端接受请求,并回应相同的信息,一旦客户端写入byebye,则结束本次操作
 *TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。
 *TCP客户端依次调用socket()、connect()之后就向TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,
 *就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。
 */
public class Server2 {

    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor (10,50,5, TimeUnit.SECONDS,new LinkedBlockingQueue<> (100));

    public static void main(String[] args) throws Exception{

        //通常服务端在启动的时候回绑定一个众所周知的地址(ip+端口)用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动
        //分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
        ServerSocket serverSocket = new ServerSocket (9001);//初始化socket,对端口进行绑定,并且对端口进行监听
        //这里要用一个while来接受不断发过来的请求,,但是因为accept会阻塞,故这里必须用线程
        while (!serverSocket.isClosed ()){
            Socket socket = serverSocket.accept ();//侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。这应该是一个一直在进行的新线程,因为她面对的可能是诸多追求者
            if (socket.isConnected ()){
                System.out.println ("连接成功男朋友为:" + socket.toString ());
            }
            threadPoolExecutor.execute (() -> {
                try {
                    PrintStream out = new PrintStream (socket.getOutputStream ());//发送输入的数据  以打印流的方式
                    Scanner in = new Scanner (socket.getInputStream());//扫描流负责接受客户端发来的请求,一直不断变化的,因为socket是不断变化的
                    while (true){
                        if (in.hasNext ()){//阻塞的方法 inputStream类的read()方法
                            String str = in.next ();
                            System.out.println ("接受到客户端发来的信息:" + str);
                            out.println (str);//接收到消息  并回复同等内容
                            if (str.equals ("bye")){
                                break;
                            }
                        }
                    }
                    out.close ();
                    in.close ();
                    socket.close ();
                } catch (IOException e) {
                    e.printStackTrace ();
                }

            });
        }
        System.out.println ("结束服务端");
        serverSocket.close ();

    }

}

Start a server and two clients, client send to the server: I client2, I client2_1:

Digression:

We all know the tcp socket is to comply with the agreement, that if a browser to access my server work? Our test: is obviously not feasible because the browser requests a http request, obvious that client requests are sent me, but the response to the browser is indeed invalid because protocol is inconsistent, so only need to return to a fixed format data (based on http protocol) to the client can be.

Rewrite the code (return http format):

package NIO.serverpkg;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerHttp {


    public static void main(String[] args) throws Exception{

        ServerSocket serverSocket = new ServerSocket (9001);
        while (!serverSocket.isClosed ()){
            Socket socket = serverSocket.accept ();
            if (socket.isConnected ()){
                System.out.println ("连接成功男朋友为:" + socket.toString ());
            }
            InputStream in = socket.getInputStream ();
            BufferedReader reader = new BufferedReader(new InputStreamReader (in, "utf-8"));
            String msg = "";
            while ( (msg = reader.readLine () ) != ""){
                System.out.println (msg);
                if (msg.length () == 0){
                    break;
                }
            }
            System.out.println("收到数据,来自:"+ socket.toString());
            OutputStream out = socket.getOutputStream ();
            out.write("HTTP/1.1 200 OK\r\n".getBytes());
            out.write("Content-Length: 11\r\n\r\n".getBytes());
            out.write("Hello World".getBytes());
            out.flush();
        }
        System.out.println ("结束服务端");
        serverSocket.close ();

    }

}

http format is as follows:

Under the above is to demonstrate it, get down to business, multi-threaded or fixed thread pool this design is problematic, as the concurrent high, the thread will appear the situation is not enough, and when the business logic threading belong consuming operations io or long-term occupation is not when the connection is closed, the case must be enough thread will appear, will rise to a performance problem, then how to solve it?

Introducing the topic of NIO

 

Guess you like

Origin blog.csdn.net/qq_40826106/article/details/82665716