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);
第二行代碼,一旦套接字被打開,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();
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();
}
}
}