【JavaSE學習筆記】- 網絡編程

Java 學習--網絡編程(一)

關鍵字:InetAddress UDP TCP Socket

1、網絡參考模型

OSI參考模型

TCP/IP參考模型

應用層

 

應用層

表示層

會話層

傳輸層

傳輸層

網絡層

網際層

數據鏈路層

主機

及網絡層

物理層











2、IP地址:InetAddress類

此類表示互聯網協議 (IP) 地址。如果需要在主機名和因特網地址之間進行轉換時就需要用到該類。常用方法如下:

靜態的getByName方法可以返回代表某個主機的InetAddress對象:

InetAddress address = InetAddress.getByName("time-A.thimefreq.bldrdoc.gov");

可以使用getAddress方法來訪問InetAddress對象裏面封裝好的序列:

byte[] addressBytes = address.getAddress();

還可以通過調用getAllByName方法來獲得所有主機:

InetAddress[] addresses = InetAddress.getAllByName(host);

有時候還需要知道本地主機的地址,此時可以使用靜態的getLocalHost方法來得到本地主機的地址:

InetAddress address = InetAddress.getLocalHost();

示例如下:

import java.net.*;
class InetAddressTest
{
	public static void main(String[] args)
	{
		try{
			if(args > 0)
			{
				String host = args[0];
				InetAddress[] address = InetAddress.getAllByName(host);
				for(InetAddress a:address)
				{
					System.out.println(a);
				}
			}else
			{
				InetAddress localHostAddress = InetAddress.getLocalHost();
				System.out.println(localHostAddress);
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

3、 傳輸協議:UDP和TCP

        TCP 是Tranfer Control Protocol的簡稱,是一種面向連接的保證可靠傳輸的協議。通過TCP協議傳輸,得到的是一個順序的無差錯的數據流。發送方和接收方的成對的兩個socket之間必須建立連接,以便在TCP協議的基礎上進行通信,當一個socket(通常都是server socket)等待建立連接時,另一個socket可以要求進行連接,一旦這兩個socket連接起來,它們就可以進行雙向數據傳輸,雙方都可以進行發送或接收操作。
        UDP 是User Datagram Protocol的簡稱,是一種無連接的協議,每個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網絡上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。 

TCP和UDP的區別:

TCP:面向連接     | 傳輸可靠性可靠     | 傳輸大量數據 | 速度慢

UDP:面向非連接| 傳輸可靠性不可靠 | 傳輸少量數據 | 速度快

4、 Socket

此類實現客戶端套接字,套接字是兩臺機器間通信的端點。 Socket是爲網絡服務提供的 一種機制,網絡通信其實就是Socket之間的通信。

try{
	Socket s = new Socket("time-A.timefreq.bldrdoc.gov",13);
	try{
		InputStream inStream = s.getInputStream();
		Scanner in = new Scanner(inStream);
		while(in.hasNextLine()){
			String line = in.nextLine();
			System.out.println(line);
		}
	}
	finally{
		s.close();
	}
}
catch(IOException e){
	e.printStackTrace();
}

這個程序關鍵的幾行代碼:

Socket s = new Socket("time-A.timefreq.bldrdoc.gov",13);

Scanner in = new Scanner(inStream);

第一行代碼用於打開一個套接字,他是網絡軟件的一個抽象概念,負責時能該程序內部與外部之間的通信。我們將遠程地址和端口號傳遞給套接字的構造器,如果連接失敗它將跑出一個UnknowHostException異常,如果存在其他異常拋出IOException異常。

第二行代碼,一旦套接字被打開,java.net.Socket類中的getInputStream方法會返回一個InputStream對象,一旦獲得這個流,該程序將直接把每一行打印到輸出,這個過程一直持續到流發送完畢並且服務器斷開連接爲止。

5、 UDP的Socket建立:

  • 首先要了解兩個類:

DatagramSocket  此類表示用來發送和接收數據報包的套接字。 構造方法:DatagramSocket(int port) 創建數據報套接字並將其綁定到本地主機上的指定端口

DatagramPacket 此類表示數據報包,數據報包用來實現無連接包投遞服務。構造方法:DatagramPacket(byte[] buf, int length, SocketAddress address)  構造數據報包,用來將長度爲 length 的包發送。

  • 發送端:

1)通過DatagramSocket創建udp的Socket服務:

DatagramSocket  ds = new DatagramSocket();

2)確定數據,並封裝成數據包:

DatagramPacket  dp = new DatagramPacket(…….);

3)通過UDP的Socket服務將已有的數據包發送出去:

ds.send(dp);

4)關閉資源:

ds.close();

  • 接收端:

1)  通過DatagramSocket創建udp的Socket服務,通常在這裏設置一個監聽端口,用以指定該接收斷處理哪個端口發來的數據:DatagramSocket  ds = newDatagramSocket(int  mark);

2)  定義一個用來存儲接收到的數據的空數據包:

DatagramPacket  dp = newDatagramPacket(…….);

3)  通過udp的Socket服務將將接收到的數據包存儲在第2步中定義的空數據包中。

ds.receive(dp);

4)  通過數據包的方法獲取器中的數據。

InetAddress  getAddress()返回某臺機器的 IP 地址,此數據報將要發往該機器或者是從該機器接收到的。

byte[] getData()       返回數據緩衝區。

int   getLength()   返回將要發送或接收到的數據的長度。

int   getOffset()返回將要發送或接收到的數據的偏移量。

int   getPort()返回某臺遠程主機的端口號,此數據報將要發往該主機或者是從該主機接收到的。

SocketAddress   getSocketAddress()獲取要將此包發送到的或發出此數據報的遠程主機的 SocketAddress (IP 地址 + 端號)

5)  關閉資源:

ds.close();

6、 TCP的Socket建立:

TCP的Socket建立主要涉及兩個類Socket類與ServerSocket類。Socket類實現客戶端套接字(也可以就叫“套接字”可以稱爲端口)。套接字是兩臺機器間通信的端點。ServerSocket類實現服務器套接字。服務器套接字等待請求通過網絡傳入。它基於該請求執行某些操作,然後可能向請求者返回結果。

  • 客戶端:

1)建立Socket服務,指定要連接的主機和端口:

Socket  s = new Socket(Stringhost, int port);

2)獲取Socket流中的輸出流,將數據寫到該流中,通過網絡發送給服務端:

OutputStream out = s.getOutputStream();

3)獲取Socket流中的輸入流,獲取服務端反饋的信息:

InputStream in = s.getInputStream();

4)關閉客戶端:

s.close();

  • 服務端:

1) 建立ServerSocket服務,指定要接收的端口:

ServerSocket  server = newServerSocket (int port);

2) 獲取連接到服務端的客戶端Socket:

Socket socket = s.accept();

3) 獲取Socket流中的輸出流,將數據寫到該流中,通過網絡發送給服務端:

OutputStream out =socket .getOutputStream();

4)獲取Socket流中的輸入流,獲取服務端反饋的信息:

InputStream in =socket .getInputStream();0

5) 關閉客戶端:

socket .close();

6) 關閉服務端:

server.close();

7、 使用SeverSocket實現服務器
                            API:java.net.ServerSocket 1.0                                            
ServerSocket(int port)   創建一個監控端口的服務器套接字
Socket  accept()             等待連接,該方法阻塞當前線程知道建立連接爲止
void  close()                  關閉服務器套接字

1)建立一個負責監控端口8189的服務器
ServerSocket s = new ServerSocket(8189);
2)告訴程序不停地等待知道有客戶端連接到這個端口。
Socket incoming = s.accept();
3)使用這個Socket對象得到輸入流和輸出流
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
4)將流轉換成掃描器和寫入器,以便通過套接字來發送文本
Scanner in = new Scanner(inStream);
PrintWriter out = new PrintWriter(outStream,true /*autoFlush*/);
5)對輸入進行計算並返回處理結果
String line = in.nextLine();
out.println("Echo:"+line);
6)在代碼的最後,我們關閉連接進來的套接字
incoming.close();
示例如下:
import java.io.*;
import java.net.*;
import java.util.*;
class EchoServer 
{
	public static void main(String[] args) 
	{
		try
		{
			ServerSocket s = new ServerSocket(8189);
			Socket incoming = s.accept();
			try
			{
				InputStream input = incoming.getInputStream();
				OutputStream output = incoming.getOutputStream();
				
				Scanner in = new Scanner(input);
				PrintWriter out = new PrintWriter(output,true/*autoFlush*/);
				out.println("Hello!Enter BYE to exit.");
				boolean done = false;
				while(!done && in.hasNextLine())
				{
					String line = in.nextLine();
					out.println("Echo: "+line);
					if(line.trim().equals("BYE")
						done = true;
				}
			}
			finally
			{
				incoming.close();
			}
		}
		catch (IOException e)
		{
			incoming.close();
		}
	}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章