JAva IO学習ノート[2]

5117 ワード


私は昨日javaネットワークのプログラミングを書いたとき、このようないくつかの問題を考えました.今まとめます.
 
一:TCPプログラミングはバイトストリーム向け
      私はsocketでプログラミングして、TCP/IPに基づいて、TCPプロトコルは伝送層のプロトコルで、それは接続に向いて、UDPと大きい違いは前者がバイトストリームに向かうプロトコルで、後者はユーザーデータグラムProtocolで、バイトストリームに向かって大きなメリットがあって、それは混雑制御を行うことができて、流量制御を行うことができて、エラーコントロールを行います.
       なぜUDPがダメなのか?UDPアプリケーション層が伝送層にどんなデータ新聞を送信するか、伝送層がどんなデータ新聞を送信するか、それが何バイトあるかにかかわらず、伝送が多すぎるとブロックされるのではないか.TCPは違います.アプリケーション層が転送層にデータを転送させる場合、転送層は直接送信するのではなく、バッファから1バイトずつ取り出し、TCP送信端には送信ウィンドウがあります.このウィンドウはTCPが流量制御を行い、エラー制御のコアです.受信側には受信ウィンドウがあり、要するにウィンドウの直接的なスライド(速くなったり、順序が乱れたり、フレームが失われたり)によって、以上の制御が行われる.
       ではjavaはsocketプログラミングを行うときにバイトストリームしか使えませんか?答えはそうじゃない
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;

public class Server1 {
/**    */
	public static void main(String[] args) throws IOException{
		ServerSocket ss = new ServerSocket(5678);
		
		Socket socket = ss.accept();
		
		PrintWriter out = new PrintWriter(socket.getOutputStream());
		
		BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));  
		
		while(true)
		{
			String str=in.readLine();  
			System.out.println(str);
			out.println("hello world");
			out.flush();
			
		}
	}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * socket      
 * */
public class Client1 
public static void main(String[] args)throws Exception{  
	Socket server=new Socket("localhost",5678);  
	BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));  
	PrintWriter out=new PrintWriter(server.getOutputStream());  
	BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));  
	while(true){  
		String str=wt.readLine();  
		out.println(str);  
		out.flush();  
		if(str.equals("end")){  
			break;  
			}  
		System.out.println(in.readLine());  
		}  
	server.close();  
	}  
}

以上のコードは、文字ストリーム向けの仮想イメージを使用していますが、ここでは文字ストリームがバイトストリームをカプセル化していることがわかります.ここではアダプタモードであるべきで、1つのバイトストリームを1つの文字ストリームに変換し、server.getInputStream()メソッドのソースコードは、実際に返されるバイトストリームを見ることができます.
public InputStream getInputStream() throws IOException

 
二:printとprintlnの違いはいったい何ですか.
 
ソケットプログラミングでPrintWriterクラスを出力ストリームとして使用する場合、print()ではなくprintln(String str)が必要になる理由.
       私の印象ではprintlnはprintの後ろに改行符をつけただけで、ほとんどの人が私の考えと同じだと思いますが、ソースコードを見てみると
/**
     * Prints a String and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(String)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @param x  The <code>String</code> to be printed.
     */
    public void println(String x) {
	synchronized (this) {
	    print(x);
	    newLine();
	}
    }

 public void print(String s) {
	if (s == null) {
	    s = "null";
	}
	write(s);
    }

 

 上記の2つの方法から少なくとも2点1:println方法はスレッドが安全であることがわかる:2:newLine()方法が1つ増えた.
ではnewLine()はどんな方法ですか?
   /**
    private BufferedWriter textOut;
    */
	
	private void newLine() {
	try {
	    synchronized (this) {
		ensureOpen();
		textOut.newLine();
		// BufferedWriter   newLine          
		 /**
		 * Writes a line separator.  The line separator string is defined by the
		 * system property <tt>line.separator</tt>, and is not necessarily a single
		 * newline ('
') character. * * @exception IOException If an I/O error occurs * public void newLine() throws IOException { write(lineSeparator); } */ /** * Flushes the output buffer to the underlying character stream, without * flushing the stream itself. This method is non-private only so that it * may be invoked by PrintStream. , */ textOut.flushBuffer(); /* ? */ charOut.flushBuffer(); if (autoFlush) out.flush(); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException x) { trouble = true; } }

  つまりprintlnメソッドはprintよりも多くのことをしています.改行を終了し、バッファをリフレッシュする機能がありますが、printはありません.print出力を使用すると、リフレッシュも終了もなく、単独で書き込まれます.
 
では、バッファをリフレッシュするには、いったい底で何をしたのでしょうか.