Java中網(wǎng)絡(luò)編程概述、IP地址、端口號、TCP和UDP協(xié)議、Socket、UDP傳輸、多線程UDP聊天

網(wǎng)絡(luò)編程概述

就是用來實現(xiàn)網(wǎng)絡(luò)互連的不同計算機上運行的程序間可以進行數(shù)據(jù)交換。

有人說,20世紀最偉大的發(fā)明不是計算機,而是計算機網(wǎng)絡(luò)。哈哈,的確是這樣,現(xiàn)在沒有網(wǎng),簡直不能活下去。

計算機之間要進行通訊的話要以什么樣的規(guī)則進行通信呢,這就是網(wǎng)絡(luò)模型研究的問題,我們下來學(xué)習(xí)。

網(wǎng)絡(luò)模型

  • OSI參考模型
  • TCP/IP參考模型

OSI參考模型

應(yīng)用層
表示層
會話層
傳輸層
網(wǎng)絡(luò)層
數(shù)據(jù)鏈路層
物理層

TCP/IP參考模型

應(yīng)用層
傳輸層
網(wǎng)絡(luò)層
主機至網(wǎng)絡(luò)層 

網(wǎng)絡(luò)通信三要素

  • IP地址:InetAddress
    • 網(wǎng)絡(luò)中設(shè)備的標識,不易記憶,可用主機名
  • 端口號
    • 用于標識進程的邏輯地址,不同進程的標識
  • 傳輸協(xié)議
    • 通訊的規(guī)則
      常見協(xié)議:TCP,UDP

IP地址

說起IP地址,我們每個人都知道自己的電腦有個IP地址,它在計算機中有什么作用呢?我們就來看一下它的具體概念
要想讓網(wǎng)絡(luò)中的計算機能夠互相通信,必須為每臺計算機指定一個標識號,也就是網(wǎng)絡(luò)中計算機的唯一標識,通過這個標識號來指定要接受數(shù)據(jù)的計算機和識別發(fā)送的計算機,在TCP/IP協(xié)議中,這個標識號就是IP地址。

那么,我們?nèi)绾潍@取和操作IP地址呢?java提供了一個類**InetAddress **供我們使用對IP地址的獲取和操作。

我們來獲取本機的主機名和IP地址

public class InetAddressDemo { 
public static void main(String[] args) { 
try { 
InetAddress in = InetAddress.getLocalHost(); System.out.println(in.toString()); 
} catch (UnknownHostException e) { 
e.printStackTrace(); 
}
 }
}

運行程序,我們就得到了本機的主機名和IP地址
那么我們想要知道別人的IP地址或主機名怎么辦呢?當然也是有方法的

public class InetAddressDemo { 
public static void main(String[] args) throws UnknownHostException { InetAddress address = InetAddress.getByName("192.168.2.102"); 
// public String getHostName()獲取主機名,
 String name = address.getHostName(); 
// public String getHostAddress()獲取IP地址 
String ip = address.getHostAddress(); 
System.out.println(name + "---" + ip); 
}
}

如果你和別人在一個局域網(wǎng)內(nèi),知道了他的主機名或者IP地址就可以獲取到另外一個。

端口號

端口號它分為兩種,一種是物理端口,另外一種是邏輯端口。
物理端口就是網(wǎng)卡口,我們要學(xué)的呢就是邏輯端口,它是什么呢?

  • 每個網(wǎng)絡(luò)程序都會至少有一個邏輯端口
  • 用于標識進程的邏輯地址,不同進程的標識
  • 有效端口:065535,其中01024系統(tǒng)使用或保留端口。

TCP和UDP協(xié)議

TCP和UDP協(xié)議它們是通訊的規(guī)則,它們有什么區(qū)別呢?

TCP
    建立連接,形成傳輸數(shù)據(jù)的通道
    在連接中進行大數(shù)據(jù)量傳輸
    通過三次握手完成連接,是可靠協(xié)議
    必須建立連接,效率會稍低
UDP
    將數(shù)據(jù)源和目的封裝成數(shù)據(jù)包中,不需要建立連接
    每個數(shù)據(jù)包的大小在限制在64k
    因無連接,是不可靠協(xié)議
    不需要建立連接,速度快

一般的軟件它既有UDP,又有TCP,用TCP來保證軟件的可靠性,用UDP來保證軟件的傳輸速度快。

Socket

我們繼續(xù)看Socket,我們說的網(wǎng)絡(luò)編程也就是Socket編程也叫做網(wǎng)絡(luò)套接字。

  • Socket套接字:
    • 網(wǎng)絡(luò)上具有唯一標識的IP地址和端口號組合在一起才能構(gòu)成唯一能識別的標識符套接字。
  • Socket原理機制:
    • 通信的兩端都有Socket。
    • 網(wǎng)絡(luò)通信其實就是Socket間的通信。
    • 數(shù)據(jù)在兩個Socket間通過IO傳輸。

UDP傳輸

我們要用UDP傳輸數(shù)據(jù)時,怎么用Socket建立連接呢?

  • DatagramSocket與DatagramPacket
  • 建立發(fā)送端,接收端。
  • 建立數(shù)據(jù)包。
  • 調(diào)用Socket的發(fā)送接收方法。
  • 關(guān)閉Socket。

發(fā)送端與接收端是兩個獨立的運行程序。我們用代碼實現(xiàn)一個UDP傳輸數(shù)據(jù)的例子

UDP傳輸-發(fā)送端

/* 
* 需求:接收指定端口發(fā)送過來的數(shù)據(jù)
 * 
* UDP協(xié)議發(fā)送數(shù)據(jù):
* A:創(chuàng)建發(fā)送端Socket對象 
* B:創(chuàng)建數(shù)據(jù),并把數(shù)據(jù)打包
* C:調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包 
* D:釋放資源 
*/
public class SendDemo { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建發(fā)送端Socket對象 
// DatagramSocket() 
DatagramSocket ds = new DatagramSocket();
 // 創(chuàng)建數(shù)據(jù),并把數(shù)據(jù)打包 
// DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
// 創(chuàng)建數(shù)據(jù) 
byte[] bys = "UDP過來了".getBytes();
 // 長度 
int length = bys.length;
 // IP地址對象 
InetAddress address = InetAddress.getByName("192.168.2.102"); 
// 端口
 int port = 12345; 
DatagramPacket dp = new DatagramPacket(bys, length, address, port); 
// 調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包 
// public void send(DatagramPacket p) 
ds.send(dp); 
// 釋放資源
 ds.close();
 }
}

UDP傳輸-接收端

/* * UDP協(xié)議接收數(shù)據(jù): 
* A:創(chuàng)建接收端Socket對象 
* B:創(chuàng)建一個數(shù)據(jù)包(接收容器) 
* C:調(diào)用Socket對象的接收方法接收數(shù)據(jù) 
* D:解析數(shù)據(jù)包,并顯示在控制臺 
* E:釋放資源 
*/
public class ReceiveDemo { 
public static void main(String[] args) throws IOException {
 // 創(chuàng)建接收端Socket對象 
// DatagramSocket(int port) 
DatagramSocket ds = new DatagramSocket(12345); 

// 創(chuàng)建一個數(shù)據(jù)包(接收容器) 
// DatagramPacket(byte[] buf, int length) 
byte[] bys = new byte[1024]; 
int length = bys.length; 
DatagramPacket dp = new DatagramPacket(bys, length); 

// 調(diào)用Socket對象的接收方法接收數(shù)據(jù) 
// public void receive(DatagramPacket p)
 ds.receive(dp); // 阻塞式 

// 解析數(shù)據(jù)包,并顯示在控制臺 
// 獲取對方的ip 
// public InetAddress getAddress() 
InetAddress address = dp.getAddress(); 
String ip = address.getHostAddress(); 
// public byte[] getData():獲取數(shù)據(jù)緩沖區(qū) 
// public int getLength():獲取數(shù)據(jù)的實際長度
 byte[] bys2 = dp.getData(); 
int len = dp.getLength();
String s = new String(bys2, 0, len);
 System.out.println(ip + "傳遞的數(shù)據(jù)是:" + s); 
// 釋放資源 
ds.close(); 
}
}

我們先運行接收端的代碼,再運行發(fā)送端的代碼,這樣在接收端就會收到由發(fā)送端發(fā)過來的數(shù)據(jù)。完成了UDP傳輸

多線程UDP聊天

/* 
* 通過多線程實現(xiàn)聊天程序,我們就要開啟兩個線程,一個接收數(shù)據(jù),一個發(fā)送數(shù)據(jù),這樣我就可以實現(xiàn)在一個窗口發(fā)送和接收數(shù)據(jù)了 
*/
public class ChatRoom { 
public static void main(String[] args) throws IOException { DatagramSocket dsSend = new DatagramSocket(); 
DatagramSocket dsReceive = new DatagramSocket(12345); SendThread st = new SendThread(dsSend); 
ReceiveThread rt = new ReceiveThread(dsReceive);
 Thread t1 = new Thread(st); 
Thread t2 = new Thread(rt);
 t1.start(); t2.start(); 
}
}
/* * 接收數(shù)據(jù) */
public class ReceiveThread implements Runnable {
 private DatagramSocket ds;
 public ReceiveThread(DatagramSocket ds) {
 this.ds = ds;
 } 
@Override
 public void run() { 
try { while (true) { 
// 創(chuàng)建一個包裹 
byte[] bys = new byte[1024]; 
DatagramPacket dp = new DatagramPacket(bys, bys.length); 
// 接收數(shù)據(jù) ds.receive(dp);
 // 解析數(shù)據(jù)
 String ip = dp.getAddress().getHostAddress(); 
String s = new String(dp.getData(), 0, dp.getLength()); System.out.println("from " + ip + " data is : " + s);
 } 
} catch (IOException e) { 
e.printStackTrace(); 
} 
}
}
/* * 發(fā)送數(shù)據(jù) */
public class SendThread implements Runnable { 
private DatagramSocket ds; 
public SendThread(DatagramSocket ds) { 
this.ds = ds; 
} 
@Override 
public void run() { 
try { 
// 封裝鍵盤錄入數(shù)據(jù)
 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
String line = null; 
while ((line = br.readLine()) != null) { 
if ("886".equals(line)) { 
break; 
} 
// 創(chuàng)建數(shù)據(jù)并打包
 byte[] bys = line.getBytes(); 
DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.2.102"), 12345); 
// 發(fā)送數(shù)據(jù) 
ds.send(dp); 
} 
// 釋放資源 
ds.close(); 
} catch (IOException e) { 
e.printStackTrace(); 
} 
}
}

我們只需要運行聊天室ChatRoom類,就可以完成單窗口聊天了
這里寫圖片描述

你發(fā)送一句,他就會接收一句,是不是很有意思呢?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容