IP地址,TCP/UDP通訊協議概述,Socket,UDP傳輸,多線程UDP聊天應用
一.JAVA網絡請求概述
關於JAVA的網絡請求,我們大致的可以分爲以下幾個分類
- OSI
- TCP/IP
- 網絡通訊
- IP地址
- 端口號
- 傳輸協議
拿這些都是幹嘛的呢?我們接下來都會講到
首先我們應該思考的是他們通信的一個過程的步驟
1.找到對方IP
2.數據發送到指定應用程序上,爲了識別,就有了端口的概念
3.定義通信協議(也就是後來的傳輸協議)國際協議/TCP/IP
4.三要素:IP,端口,協議
OK,那我們就研究下網絡模型,OSI和TCP/IP的區別
其實理解起來也不難,我們看一下他的邏輯結構就知道了
OSI
- 應用層
- 表示層
- 會話層
- 傳輸層
- 網絡層
- 數據鏈路層
- 物理層
TCP/IP
- 應用層
- 傳輸層
- 網絡層
- 主機-網絡層
應用層,我們就在這裏玩,TCP封裝了就比較好用,他們都有使用規則,而我們常用的大概就是HTTP協議了
二.IP地址
通訊要素大致的就是這些,我們來說一下我們耳熟能詳的IP地址,他是什麼概念呢?
IP地址
網絡中設備的標識
可用主機名
本地迴環地址:127.0.0.1,主機名:location
端口號
用於標識進程的邏輯地址,不同進程的標識
有效端口:0-65535,其中0-1024系統使用或者保留,我們熟知的8080
通訊協議
通訊的規則
常見的TCP,UDP
我們可用用代碼獲得哦,先看API文檔,會發現JAVA給我們提供了一個類InetAddress
我們可用直接去用代碼使用
try {
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost.toString());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
可以得到
這裏寫圖片描述
得到的本機的主機名和IP地址
當然,你要單獨獲取也是沒問題的
try {
InetAddress localHost = InetAddress.getLocalHost();
String hostAddress = localHost.getHostAddress();
String hostName = localHost.getHostName();
System.out.println(localHost.toString());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
三.TCP/UDP通訊協議概述
端口我們沒什麼可說的,我們直接說通訊協議,目前常見的就是TCP/UDP了,我們先來簡單的說下他們的概念
TCP
- 建立連接,形成傳輸數據的通道
- 在連接中進行大數據量傳輸
- 通過三次握手完成連接,是可靠協議
- 必須建立連接,效率稍微低點
UDP
- 將數據及源和目的封裝在數據包中,不需要建立連接
- 每個數據包的大小限制在64K內
- 因無連接,是不可靠協議
- 不需要建立連接,速度快
- 這些這麼多,java肯定會給我們封裝對象的,這個是毋庸置疑的,那我們接着往下看
四.Socket
Socket就厲害了,我們先來看看他的概念
Socket就是爲網絡服務提供的一種機制
通信的兩端都有socket
網絡通信其實就是socket通信
數據在兩個socket通過IO傳輸
我們現在先說概念,後期再實戰
五.UDP傳輸
UDP傳輸的socket服務該怎麼建立?
DatagramSocket和DatagramPacket
建立發送端和接收端
建立數據包
調用socket的發送和接收方法
關閉socket
客戶端和服務端是兩個單獨的服務,我們可用來用代碼講解下,用到的就是DatagramSocket和DatagramPacket
所以這裏應該是有兩個,一個傳輸端,一個接收端
傳輸端
/**
* 需求: 通過UDP傳輸方式將一段文字數據發送出去
* 思路:
* 1.建立UDP的socket服務
* 2.建立數據包
* 3.發送數據
* 4.關閉資源
*
* @author LGL
*
*/
public class UdpSend {
public static void main(String[] args) {
try {
// 1.建立UDP的socket服務,通過DatagramSocket對象
DatagramSocket dSocket = new DatagramSocket();
// 2.確定數據,封裝成數據包
byte[] data = "udp".getBytes();
DatagramPacket dp = new DatagramPacket(data, data.length,
InetAddress.getByName("192.168.1.102"), 8080);
// 3.發送數據
dSocket.send(dp);
// 4.關閉資源
dSocket.close();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
接收端
/**
* 需求:接收指定端口發送過來的數據
* 思路:
* 1.定義socket服務
* 2.定義數據包,存儲接收到的字節數據,因爲數據包對象中有更多功能可以提取字節數據中的不同數據信息
* 3.通過socket的receive方法收到的數據存儲到數據包中
* 4.將這些不同的數據取出,打印
* 5.關閉資源
*
* @author LGL
*
*/
class UdpRece {
public static void main(String[] args) {
try {
// 1.創建服務,建立端點
DatagramSocket dSocket = new DatagramSocket(8080);
// 2.定義數據包,存儲數據
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
// 3.存儲
dSocket.receive(dp);
// 4.獲取其中的數據
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(), 0, dp.getLength());
int port = dp.getPort();
System.out.println(ip+":" + data + ":" + port);
//5.關閉資源
dSocket.close();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
這樣就可以通信了
六.多線程UDP聊天應用
既然上面有模有樣的寫出來了,那我們可以動手寫一個應用了,我們繼續來看,我不開多個進程,我寫一個進程,兩個線程來實現聊天
/**
* 編寫一個聊天應用程序 有收數據和發數據的部分,所以用到多線程的技術,一個接一個發 收和發的動作不一致,所以有兩個Runnable
*
* @author LGL
*
*/
public class UdpSpeak {
public static void main(String[] args) {
try {
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10000);
new Thread(new send(sendSocket)).start();
new Thread(new rece(receSocket)).start();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 發送
*
* @author LGL
*
*/
class send implements Runnable {
private DatagramSocket socket;
public send(DatagramSocket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
while ((line = bufr.readLine()) != null) {
if ("close".equals(line)) {
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length,
InetAddress.getByName("192.168.1.102"), 10000);
socket.send(dp);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 接收
*
* @author LGL
*
*/
class rece implements Runnable {
private DatagramSocket socket;
public rece(DatagramSocket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true) {
try {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
socket.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(), 0, dp.getLength());
int port = dp.getPort();
System.out.println(ip + ":" + data + ":" + port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
OK,搞定,其實主要還是要了解他的思想,編碼什麼的不重要的
好了,本篇主要是以UDP和概念爲起點,而且UDP用的較少,我們一般不是常接觸,真正要用的是TCP,所以會重點掌握,那本篇,我們先到這裏就好了