BIO初期ネットワークプログラミング、NIO

       あなたが手を振って4とのスリーウェイハンドシェイクを求められることがありますインタビューについて話す前に?

       Bへの送信は、初期通信を確立し、問題分散でA、B、Bが受信され、AとBに送信される都会の文字を想定しています。三波は、Aは、受信およびBの伝送能力がOKであり、従って証明された接続が正常であることを証明することです。

        最初のハンドシェイク:AがBに送信すると、Bは手紙を受け取り、都市Bを理解するために、この時、伝送容量と市はokです受信容量B市。

        セカンドハンドシェイク:BがAに送信されると、Aは一方で、手紙、その後、都市Aが理解し、伝送容量とA市BがOKである都市の受信能力に加え、前回の送信を受けましたまた、受信B市の(独自の)シグナリング機能および能力を知っている両側がOKである知っているが、それは、Aは今回が初めてであるがため、Bも、困惑に相当する、OKであります自分の能力を受信するシグナリング機能はOKですが、シグナリング能力と都市の能力タウンB(自体)を受信して​​いない方法を知っているので、第三のハンドシェイクを必要としません。

        サードハンドシェイク:Bが、あなたは両側があまりにも多く、それTaoxintaofeiハイ終わりを知っているので、B(そのシグナリング機能)と受信機の能力市は、もOKです知っているとき、Bに発行された領収書そのためにも根拠。最初の通信の確立を完了します。

       おそらく、次の図に示すフロー:

TCP 3ウェイハンドシェイクプロトコル 接続したら、それは結論することができます
まず握手A - > B 締結:私はOK送る場合は、わからないが知っているされていないものを 
B結論:脂肪B近いOK]を 
セカンドハンドシェイクB - > A 結論は、描画することができます:ヘアコレクションBを加え、最初の送信の導入は、収入の前に[OK] Bを送ることができ、私は大丈夫ですAB送信側と受信側の理解できる
Bを締結:B髪近いOKに基づいて、第1回が、それは成功とAを受け入れるために、独自の能力を送信するかどうかわかりません
第三に握手A - > B Bは、受信した後に送信Bは、メッセージが証明できる:A及びBを受信する自己OKシグナリング能力と容量

実際には、これは私がモジュールに関与していた前にしなければならなかった、ログのダウンロード機能を執筆を担当した、その実装が完了するのB / S構造の使用は、それは、ソケットプログラミングの使用を達成するために、マルチスレッドのような組み合わせでは、されています機能。入力ストリームクラスread()メソッドがブロックされているので、上のすべての毛、マルチスレッドまたはスレッドプールつの要求を使用する必要があるので、サーバなどのデバイス(ソースログ)、クライアント(再送要求)などのブラウザは、通信を形成しますしたがって、新しいスレッドを使用して互いに干渉し、ここでの操作上の私は(チャットのように)アナログ少しデモです。

クライアントコード:

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 ();
    }

}

サーバーコード:

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 ();

    }

}

サーバーと2つのクライアントを起動し、クライアントがサーバーに送信:私はCLIENT2、私がclient2_1:

余談:

我々は、すべてのTCPソケットがあれば、ブラウザは私のサーバーの作業にアクセスするためにことを、契約を遵守することです知っていますか?私たちのテストは:ブラウザがクライアントの要求は私を送っていることを、明らかにHTTPリクエストを要求したが、プロトコルが矛盾しているため、ブラウザへの応答が実際に無効であるため、これだけ固定フォーマットに戻る必要があり、明らかに現実的ではありませんクライアントへのデータ(HTTPプロトコルに基づく)にすることができます。

コード(リターンHTTP形式)を書き換え:

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形式は次のとおりです。

上記のことを実証することであるもとで、仕事に取り掛かる、マルチスレッドまたはこの設計は、同時高いと、問題のあるスレッドプールを固定し、状況を表示しますスレッドは十分ではありません、そしてスレッドが操作を消費属するビジネスロジックがioの場合や、長期的な職業ではありません接続が閉じられるとき、ケースは、スレッドが表示されます十分でなければならない、それを解決するためにどのようにして、パフォーマンスの問題に上昇しますか?

NIOのトピックをご紹介

 

おすすめ

転載: blog.csdn.net/qq_40826106/article/details/82665716