Socketプログラミング基盤:TCPプロトコルに基づくネットワークプログラミング


一、概説
TCPプロトコルを学習する前に,ネットワークプログラミングにおけるいくつかの基本概念を理解する必要がある.
  • IPプロトコル:インターネットProtocolの外国語略称で、コンピュータネットワークが相互に接続して通信するために設計されたプロトコル.インターネットでは、インターネットに接続されたすべてのコンピュータネットワークを相互通信させることができるルールであり、コンピュータがインターネット上で通信を行う際に遵守すべきルールを規定している.いかなるメーカーが生産したコンピュータシステムも、IPプロトコルを守ればインターネットと相互接続できる.IPアドレスに一意性がある.
  • TCPプロトコル:TCPプロトコルはエンドツーエンドプロトコルと呼ばれる.IP環境でのデータの信頼性の高い伝送を提供し、データストリーム伝送、信頼性、有効なフロー制御、フルデュプレクス動作、多重化を含むサービスを提供します.接続向け、エンドツーエンド、信頼性の高いパケットで送信します.通俗的には、送信されたデータに接続するチャネルを予め開いてから、データ送信
  • を行う.
  • ポート番号Port:主にコンピュータが異なるアプリケーションへの接続を区別するために使用します.注意:0-1023は使用できません.システムはすでに占有されています.

  • 二、Javaの基本的なネットワークサポート
  • InetAddress
  • を使用
  • URLDecoderとURLEncoder
  • URL、URLConnetction(これは後述)InetAddressの簡単な使い方
  •  public static void main(String[] args) throws Exception {
            InetAddress ia = InetAddress.getLocalHost() ;
            System.out.println("ip:" + ia.getHostAddress());
            System.out.println("   :" + ia.getHostName());
        }

    URLDecoderとURLEncoder
    URLDecoderとURLEncoderは、完了文字列とアプリケーション/x-www-form-urlencode MIME文字列との相互変換である
  • URLDecoderのdecode()メソッドは、文字列
  • に文字列でない文字列に変換することができる.
  • URLEncoderのencode()メソッドは、乱符号化されていないように見える文字列
  • にアプリケーション/x-www-form-urlencode MIMEに変換することができる.
    public static void main(String[] args) throws Exception {
            String keyword = URLEncoder.encode("  ");
            System.out.println(keyword);
            keyword = URLDecoder.decode(keyword) ;
            System.out.println(keyword);
        }

    三、通信フロー
    サービス側
    コンピュータが通信エンティティの要求を受け入れることができるクラスはServerSocketであり、ServerSocketはクライアント対応のsocketを傍受するために使用され、一般的にwhile(true)ではServerSocketを使用してsocketを絶えず取得し、接続を使用しないと待機状態になります.
    一般的なapi:
  • accept():クライアントsocketの接続要求を取得します.この方法は、クライアントに対応するsocketを返します.そうしないと、待機状態になり、スレッドがブロックされます.
  • ServerSocket(int port):指定したポート番号で0~65535の間にServerSocketを作成します.上に述べたように、0-1023は使わないでください.
  • Server Socket(int port,int backlog):接続キューの長さを変更するパラメータを追加します.
  •  //1.  socketserver,  3000  
            ServerSocket ss = new ServerSocket(30000) ;
            while(true){
                Socket s = ss.accept();
                //2.       PrintStream
                PrintStream ps = new PrintStream(s.getOutputStream()) ;
                //3.  IO  
                ps.println("hello socket,i am from SocketServer");
                //4.  
                ps.close(); 
                s.close() ;
            }

    クライアント
    クライアントは、通常、Socketのコンストラクタ接続を使用してサーバコンストラクタを次のように指定します.public Socket(String host, int port)は、次のように使用します.
    //1.  socket
            Socket s = new Socket("127.0.0.1",30000) ;
            BufferedReader br = new BufferedReader(new      InputStreamReader(s.getInputStream())) ;
            String line = br.readLine();
            System.out.println("     :" + line );
            s.close() ;

    上の127.0.0.1はローカルIPに接続されています.C:WindowsSystem 32driversetcというディレクトリのhostファイルに表示できます.上記のプログラムはまずサービス側を実行し、クライアントを実行すると通信できます.サービス側、クライアントが対応するsocketに接続されると、プログラムはサービス側、クライアントを区別する必要がなくなり、両者はそれぞれのsocket通信を通じて通信される.socketは、次の2つのapiによって出力ストリーム、入力ストリームを取得する.
     public InputStream getInputStream()
     public OutputStream getOutputStream() 

    四、マルチスレッドを入れる
    上のclient,serverは単純な通信であり,次にマルチスレッドを含むsocket通信を実現する.サービス側では、socket入力ストリームの内容、すなわちクライアントから送信されたデータを読み取り、クライアント情報に戻って受信したことを示すマルチスレッドスレッドを作成します.
    サービス側コード:
        public static ArrayList<Socket> socketList = new ArrayList<Socket>() ;
    
        public static void main(String[] args) throws Exception {
            ServerSocket ss = new ServerSocket(30001) ;
            while(true){
                Socket s = ss.accept() ;
                //      socket,      
                socketList.add(s) ;
                //        
                new Thread(new ServerThread(s)).start();
            }
        }

    サービス側は、クライアントからのSocketを格納するセットを作成し、socketを取得するたびに、通信トラフィックを処理するためのスレッドを開始します.
    class ServerThread implements Runnable{
        //   socket
        Socket s = null ;
        //  socket    
        BufferedReader br = null ;
        public ServerThread(Socket s ) throws IOException{
            this.s = s ;
            br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;
        }
    
        public void run() {
            String context ;
            while((context=readFromClient())!= null ){
                for (Socket s : MyServer.socketList) {
                    System.out.println("        :" + context );
                    PrintStream ps;
                    try {
                        ps = new PrintStream(s.getOutputStream());
                        ps.println(context + "---     ");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
            }
        }
    
        public String readFromClient(){
            try {
                return br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
                //  socket
                MyServer.socketList.remove(s);
            } 
            return null ;
        }
    }

    クライアントコード:
    public static void main(String[] args) {
            //1.  socket
            try {
                Socket s = new Socket("127.0.0.1",30001) ;
                //2.          
                new Thread(new ClientThread(s)).start() ;
                //3.  socket      
                PrintStream ps = new PrintStream(s.getOutputStream()) ;
                String line = null ;
                //4.    
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
                while((line = br.readLine())!= null ){
                    //5.       socket    
                    ps.println(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    重要な点はすでに注釈して、コードは異なって、理解できると信じています.これでマルチスレッドの通信が完了したのか、それとも上と同じようにserverを実行してからclientを実行し、実行することで各クライアントが他のクライアントの情報を見ることができるのかを知ることができます.
    Ok、この編はもう終わりました.この編はSocketの基礎を簡単に紹介しただけで、後で詳細な分析を続け、UDPネットワークベースのプログラミングを紹介します.
    ソースのダウンロード