ダークホースプログラマー——ネットワークプログラミング

7900 ワード

------- androidトレーニング、javaトレーニング、あなたとの交流を期待しています。--------
今日はjavaのネットワークプログラミングを見てみます。
      ネットワークプログラミングとは、2つ以上のデバイス(例えばコンピュータ)間でデータを伝送することである。プログラマが行っていることは、指定された位置にデータを送信したり、指定されたデータを受信したりすることです。これは狭義のネットワークプログラミングの範疇です。データを送信して受信する場合、ほとんどのプログラム設計言語は専用のAPIを設計してこれらの機能を実現しています。プログラマは呼び出しだけでいいです。ネットワーク上の各デバイスを便利に識別するために、ネットワーク内の各デバイスは一意のデジタルタグを持っています。これがIPアドレスです。コンピュータネットワークでは、現在の名前付きIPアドレスの規定は、各IPアドレスが4つの0−255間のデジタルから構成される、例えば10.0.20.34と規定されているIPv 4プロトコルである。各アクセスネットワークのコンピュータは一意のIPアドレスを持っています。このIPアドレスは固定されているかもしれません。例えば、ネットワーク上の様々なサーバ、例えばADSLダイヤルを使用してインターネットを利用するブロードバンドユーザは、どのような方法で取得されても固定されていなくても、各コンピュータはネットワーク上で唯一の合法的なIPアドレスを持っています。携帯番号ごとに同じです。しかし、IPアドレスは覚えにくいので、覚えやすくするために、別の概念であるドメイン名(Domain Name)、例えばsohu.comなどが作られました。一つのIPアドレスは複数のドメイン名に対応でき、一つのドメイン名は一つのIPアドレスにしか対応できない。ネットワークで伝送されるデータは、すべてIPアドレスをアドレスとして識別するため、実際にデータを転送する前にドメイン名をIPアドレスに変換する必要があります。このような機能を実現するサーバーをDNSサーバと呼びます。いわゆるドメイン解析と呼びます。例えば、ユーザがブラウザでドメイン名を入力すると、ブラウザはまずDNSサーバを要求し、ドメイン名をIPアドレスに変換し、その後、変換されたIPアドレスをブラウザにフィードバックして、実際のデータ転送を行う。DNSサーバが正常に動作している場合、IPアドレスまたはドメイン名を使用して、コンピュータネットワーク内のあるデバイス、例えばサーバコンピュータを簡単に見つけることができる。DNSが正常に動作していない場合は、IPアドレスを介してのみデバイスにアクセスできます。したがって、IPアドレスの使用はドメイン名より一般的です。IPアドレスとドメイン名はネットワークでコンピューターを見つける問題をよく解決しましたが、一つのコンピュータが同時に複数のネットワークプログラムを実行できるようにするために、もう一つの概念であるポートを導入しました。IPアドレスとポートの概念があったら、ネットワーク通信交換を行う時、IPアドレスを通じてこのコンピュータを検索して、ポートを通じてこのコンピュータ上の唯一のプログラムを識別することができます。これでネットデータの交換ができます。
        ネットワークで一般的に使用される2つのネットワーク通信プロトコルは、TCP(転送制御プロトコル)/UDP(ユーザデータグラムプロトコル)である。 ネットワーク通信においては、TCP方式は電話をかけるのと同様に、この方式でネットワーク通信を行う場合には、専用の仮想接続を確立し、信頼できるデータ転送を行う必要があり、データ送信が失敗したら、クライアントは自動的にデータを再送信する。UDP方式は、メールの送信と同様に、このような方法でネットワーク通信を行う場合には、専用の仮想接続を確立する必要がなく、送信も信頼できない。もし送信に失敗したら、クライアントは獲得できない。TCPは専用の仮想接続を確立して転送が正しいか確認する必要があるため、TCP方式を使う速度はやや遅く、また伝送時に発生するデータ量はUDPより少し大きい。
私たちはUDPプロトコルを採用したネットワーク通信プログラムを見ます。
import java.net.*;
/**
*
*	  UDP     
*/
public class DatagramSocketReceive{
	public static void main(String[] agrs) throws Exception{
		DatagramSocket ds = new DatagramSocket(3000);//             
		//      1024   ,      1024   
		DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
		//    
		ds.receive(dp);
		byte[] buf = dp.getData();//           
		int length = dp.getLength();//       ,     1024         
		String str = new String(buf,0,length);
		System.out.println(str);
		ds.close();
	}
}
import java.net.*;
/**
*
*	  UDP     
*/
public class DatagramSocketSender {
	public static void main(String[] agrs) throws  Exception{
		DatagramSocket ds = new DatagramSocket();//        ,            Ip
		String str = "     。。。。@#!#";
		//                        ,       ,       ,       byte  
		DatagramPacket dp = new DatagramPacket(str.getBytes(),str.getBytes().length);
		//  ip   
		InetSocketAddress isa = new InetSocketAddress("127.0.0.1",3000);
		dp.setSocketAddress(isa);
		ds.send(dp);
		ds.close();
	}
}
次にTCPプロトコルのプログラミングを見てみます。
package cn.itcast;

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

public class ThreadScopeDataShare {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(3000);
		BufferedReader br = null;
		InputStream is = null;
		Socket s = null;
		while (true) {//         ,          socket        
			s = ss.accept();
			System.out.println("        。。。");
			is = s.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			String str = null;
			while ((str = br.readLine()) != null) {
				System.out.println(str);
			}
		}
	}
}
package cn.itcast;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class B {
	public static void main(String[] args) throws Exception {
		Socket s = new Socket("127.0.0.1", 3000);
		OutputStream os = s.getOutputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		bw.write("45454rgfdfdg        #$#@@@@@#&*&");
		bw.newLine();
		bw.close();
		os.close();
		s.close();
	}
}
上記のTCPウィジェットも動作することができますが、彼は単一スレッドで、クライアントを維持することができます。どのように複数のクライアントを維持できるTCPサーバを作成すればいいですか?
1、TCPサーバは複数のクライアントと接続したいなら、彼はaccept方法を呼び起こして、接続をスキャンし続ける必要があります。
2、サーバと各クライアントとのセッションプロセスは互いに独立しているので、各セッションを独立したスレッドで実行させ、邪魔にならないようにします。
3、スレッドサーバオブジェクトは、1つのサーバ端のソケットオブジェクトに関連して、共同でセッションを完了する必要があります。
コードを見てみますが、下のプログラムはあまり丈夫ではありません。これを異常処理します。異常を捕まえたら、フローとsocketをオフにします。
package cn.itcast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
	public static void main(String[] args) {
		Socket s = null;
		InputStream in = null;
		OutputStream out = null;
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			s = new Socket("127.0.0.1", 8000);
			String str = null;
			Scanner scanner = new Scanner(System.in);
			while ((str = scanner.nextLine())!=null) {
				in = s.getInputStream();
				out = s.getOutputStream();
				br = new BufferedReader(new InputStreamReader(in));
				bw = new BufferedWriter(new OutputStreamWriter(out));
				bw.write(str);
				bw.newLine();
				bw.flush();
				if(str.equals("quit")){//                     
					destroy(s,br,bw,scanner);
					break;
				}
				System.out.println("     "+s.getInetAddress()+"   "+br.readLine());
				
			}
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void destroy(Socket s,BufferedReader br,BufferedWriter bw,Scanner scanner){
		try {
			br.close();
			bw.close();
			s.close();
			scanner.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
package cn.itcast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.Scanner;

public class ServerTest {
	public static void main(String[] agrs) {
		ServerSocket ss = null;
		try {
			ss = new ServerSocket(8000);
		} catch (IOException e) {
			e.printStackTrace();
		}
		while (true) {
			Socket s = null;
			try {
				s = ss.accept();
				System.out.println(s.getInetAddress()+"      ");
			} catch (IOException e) {
				e.printStackTrace();
			}
			new Thread(new ServiceTotal(s)).start();
		}
	}
}

class ServiceTotal implements Runnable {
	private Socket s;

	public ServiceTotal() {
	}

	public ServiceTotal(Socket s) {
		this.s = s;
	}

	public void run() {
		try {
			InputStream in = s.getInputStream();
			OutputStream out = s.getOutputStream();
			BufferedReader bf = new BufferedReader(new InputStreamReader(in));
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
			String str = null;
			while((str = bf.readLine())!=null){
				if(bf.equals("quit")){
					destroy(s, bf, bw);
					break;
				}
				System.out.println("  "+s.getInetAddress()+"      -----"+ str);
				bw.write(new StringBuffer(str).reverse().toString());
				bw.newLine();
				bw.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	public static void destroy(Socket s,BufferedReader br,BufferedWriter bw){
		try {
			br.close();
			bw.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}