Java網(wǎng)絡(luò)編程基礎(chǔ)詳解
網(wǎng)絡(luò)編程
1.1 概述
1.2、網(wǎng)絡(luò)通信的要素
如何實(shí)現(xiàn)網(wǎng)絡(luò)通信?
1.網(wǎng)絡(luò)編程中有兩個(gè)主要的問(wèn)題
- 如何定位到網(wǎng)絡(luò)上的一臺(tái)或者多臺(tái)主機(jī)
使用cmd——>ping命令,ping一個(gè)域名,可以看到訪問(wèn)的主機(jī)的IP地址
- 找到主機(jī)之后,如何進(jìn)行通信。
2.網(wǎng)絡(luò)編程中的三要素
- IP
- 端口號(hào)
- 網(wǎng)絡(luò)通信協(xié)議(udp,tcp類)
1.3、IP
要想讓網(wǎng)絡(luò)中的計(jì)算機(jī)能夠互相通信,必須為每臺(tái)計(jì)算機(jī)指定一個(gè)標(biāo)識(shí)號(hào),通過(guò)這個(gè)標(biāo)識(shí)號(hào)來(lái)指定要接收數(shù)據(jù)的計(jì)算機(jī)和識(shí)別發(fā)送的計(jì)算機(jī),而lP地址就是這個(gè)標(biāo)識(shí)號(hào)。也就是設(shè)備的標(biāo)識(shí)
ip地址:InetAddress
- 使用IP可以唯一定位一臺(tái)網(wǎng)絡(luò)上的計(jì)算機(jī)
- 本機(jī)IP 127.0.0.1 本機(jī)localhost(唯一一個(gè)沒(méi)網(wǎng)也能ping得通得ip)
- ip地址的分類
- ipv4/ipv6
- 公網(wǎng)(互聯(lián)網(wǎng))/私網(wǎng)(局域網(wǎng))
可以用InetAddress查詢Ip地址。
public class TestInetAddress {
public static void main(String[] args) {
try {
//查詢網(wǎng)站IP地址
InetAddress ip1 = InetAddress.getByName("www.baidu.com");
System.out.println(ip1);//www.baidu.com/163.177.151.109
//查詢本機(jī)
InetAddress ip2 = InetAddress.getLocalHost();
System.out.println(ip2);//飛雷神/192.168.153.1
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
還有一個(gè)InetSocketAddress類
1.4、端口
網(wǎng)絡(luò)的通信,本質(zhì)上是兩個(gè)應(yīng)用程序的通信。每臺(tái)計(jì)算機(jī)都有很多的應(yīng)用程序,那么在網(wǎng)絡(luò)通信時(shí),如何區(qū)分這些應(yīng)用程序呢?如果說(shuō)IP地址可以唯一標(biāo)識(shí)網(wǎng)絡(luò)中的設(shè)備,那么端口號(hào)就可以唯一標(biāo)識(shí)設(shè)備中的應(yīng)用程序了。也就是應(yīng)用程序的標(biāo)識(shí)
- 不同的進(jìn)程有不同的端口號(hào),用來(lái)區(qū)分應(yīng)用程序
- 被規(guī)定
- TCP 0~65535
- UDP 0~65535
- 單個(gè)協(xié)議下,端口不沖突就可以使用。
- 端口分類
- 公有端口0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
- 公有端口0~1023
- 程序注冊(cè)端口012~49151
- Tomcat:80
- mysql:3306
- Oracle:1521
- 動(dòng)態(tài)、私有
1.5、通信協(xié)議
協(xié)議:計(jì)算機(jī)網(wǎng)絡(luò)中,連接和通信的規(guī)則被稱為網(wǎng)絡(luò)通信協(xié)議
UDP協(xié)議
用戶數(shù)據(jù)報(bào)協(xié)議(User Datagram Protocol)
- UDP是無(wú)連接通信協(xié)議,即在數(shù)據(jù)傳輸時(shí),數(shù)據(jù)的發(fā)送端和接收端不建立邏輯連接。簡(jiǎn)單來(lái)說(shuō),當(dāng)一臺(tái)計(jì)算機(jī)向另外一臺(tái)計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí),發(fā)送端不會(huì)確認(rèn)接收端是否存在,就會(huì)發(fā)出數(shù)據(jù),同樣接收端在收到數(shù)據(jù)時(shí),也不會(huì)向發(fā)送端反饋是否收到數(shù)據(jù)。
- 由于使用UDP協(xié)議消耗資源小,通信效率高,所以通常都會(huì)用于音頻、視頻和普通數(shù)據(jù)的傳輸
- 例如視頻會(huì)議通常采用UDP協(xié)議,因?yàn)檫@種情況即使偶爾丟失一兩個(gè)數(shù)據(jù)包,也不會(huì)對(duì)接收結(jié)果產(chǎn)生太大影響。但是在使用UDP協(xié)議傳送數(shù)據(jù)時(shí),由于UDP的面向無(wú)連接性,不能保證數(shù)據(jù)的完整性,因此在傳輸重要數(shù)據(jù)時(shí)不建議使用UDP協(xié)議
TCP協(xié)議
傳輸控制協(xié)議(Transmission Control Protocol)
- TCP協(xié)議是面向連接的通信協(xié)議,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接,然后再傳輸數(shù)據(jù),它提供了兩臺(tái)計(jì)算機(jī)之間可靠無(wú)差錯(cuò)的數(shù)據(jù)傳輸。在TCP連接中必須要明確客戶端與服務(wù)器端,由客戶端向服務(wù)端發(fā)出連接請(qǐng)求,每次連接的創(chuàng)建都需要經(jīng)過(guò)“三次握手”
- 三次握手:TCP協(xié)議中,在發(fā)送數(shù)據(jù)的準(zhǔn)備階段,客戶端與服務(wù)器之間的三次交互,以保證連接的可靠
第一次握手,客戶端向服務(wù)器端發(fā)出連接請(qǐng)求,等待服務(wù)器確認(rèn)
第二次握手,服務(wù)器端向客戶端回送一個(gè)響應(yīng),通知客戶端收到了連接請(qǐng)求
第三次握手,客戶端再次向服務(wù)器端發(fā)送確認(rèn)信息,確認(rèn)連接
形象記憶 三次握手(連接) A:你愁啥? 發(fā)送請(qǐng)求 B:瞅你咋地? 回應(yīng)請(qǐng)求 A:來(lái)干一場(chǎng)! 確認(rèn)鏈接 四次揮手:(斷開(kāi))
1.6、TCP模擬通信
客戶端
1.連接服務(wù)器
2.發(fā)送消息
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客戶端
public class TcpClientDemo01 {
private static OutputStream os;
private static Socket socket;
public static void main(String[] args) {
try {
//1.獲得服務(wù)器的地址、端口號(hào)
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port=9999;//服務(wù)器的端口號(hào)
//2.創(chuàng)建一個(gè)Sock連接
socket = new Socket(serverIP,port);
//使用該鏈接發(fā)送IO流消息
os = socket.getOutputStream();
os.write("你好,吃飯了嗎?".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {//關(guān)閉資源
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服務(wù)器
1.建立服務(wù)的端口
2.等待用戶連接
3.接收用戶的消息
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo01 {
private static ServerSocket serverSocket;
private static Socket socket;
private static InputStream stream;
private static ByteOutputStream baos;
public static void main(String[] args) throws IOException {
try {
//給自己一個(gè)地址,端口號(hào)
serverSocket = new ServerSocket(9999);
while(true) {
//等待客戶端連接
socket = serverSocket.accept();
//讀取客戶端的消息
stream = socket.getInputStream();
//管道流
baos = new ByteOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = stream.read(bytes)) != -1) {
baos.write(bytes, 0, len);
}
System.out.println(baos.toString());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
baos.close();
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket.close();
}
}
}
文件上傳
客服端上傳文件
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo02 {
public static void main(String[] args) throws Exception {
//創(chuàng)建一個(gè)Socket連接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//socket的輸出流
OutputStream os = socket.getOutputStream();
//讀取文件的流
FileInputStream fis = new FileInputStream("bg.jpeg");
//寫(xiě)出文件
byte[] bytes = new byte[1024];//緩沖區(qū)
int len;
while ((len = fis.read(bytes)) != -1) {//讀到緩沖區(qū)
os.write(bytes, 0, len);//從緩沖區(qū)寫(xiě)到輸出流
}
//通知服務(wù)器,我已經(jīng)上傳完成
socket.shutdownOutput();
//接收確定服務(wù)器接收完畢的信息,斷開(kāi)連接
InputStream inputStream = socket.getInputStream();
ByteOutputStream bost = new ByteOutputStream();
byte[] bytes2 = new byte[1024];
int len2;
while ((len2 = inputStream.read(bytes2)) != -1) {
bost.write(bytes2,0,len2);
}
System.out.println(bost.toString());
//關(guān)閉資源
bost.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
服務(wù)器接收文件
package com.yong.tcp;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
//創(chuàng)建鏈接
ServerSocket serverSocket = new ServerSocket(9000);
//監(jiān)聽(tīng)客戶端的連接
Socket socket = serverSocket.accept();
//獲取輸入流
InputStream inputStream = socket.getInputStream();//阻塞式監(jiān)聽(tīng),會(huì)一直等待
//文件輸出
FileOutputStream fos = new FileOutputStream("receiver.jpeg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
//通知客戶端,我已接收完畢
OutputStream os = socket.getOutputStream();
os.write("我接收完畢了,可以斷開(kāi)鏈接了".getBytes());
//關(guān)閉資源
os.close();
fos.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
1.7、UDP
UDP消息發(fā)送(聊天實(shí)現(xiàn))
發(fā)送方
package com.yong.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class ChatSendDemo01 {
public static void main(String[] args) throws Exception {
//建立一個(gè)端口
DatagramSocket socket = new DatagramSocket(8888);
//建立一個(gè)包裹
//準(zhǔn)備數(shù)據(jù),從控制臺(tái)
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String data = reader.readLine();//控制臺(tái)控制輸入
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, data.length(), new InetSocketAddress("localhost", 9999));
//發(fā)送包裹
socket.send(packet);
if ("bye".equals(data)) {
break;
}
}
socket.close();
}
}
接收方
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ChatReceiverDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(9999);
while (true) {
//準(zhǔn)備接收包裹
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
socket.receive(packet);//阻塞式接受包裹
byte[] data = packet.getData();//拿出消息
String receiveData = new String(data, 0, data.length);//轉(zhuǎn)為字符串,注意不要導(dǎo)錯(cuò)包
System.out.println(receiveData);
//退出接收
if ("bye".equals(receiveData.trim())) {
break;
}
}
socket.close();
}
}
1.8、URL
實(shí)例:
爬取網(wǎng)絡(luò)資源,url是網(wǎng)絡(luò)資源的地址
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class UrlDown {
public static void main(String[] args) throws Exception {
//下載地址,
URL url = new URL("https://m701.music.126.net/20210813190206/833ba2325a035b223f2f315a7a5b1d4f/jdyyaac/0353/055e/565e/4910a621a524e5158013a4ccdad535d9.m4a");
//連接到這個(gè)資源
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
FileOutputStream fos = new FileOutputStream("富士山下(陳奕迅).m4a");
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
fos.close();
is.close();
connection.disconnect();//斷開(kāi)連接
}
}
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Mybatis-Plus實(shí)現(xiàn)只更新部分字段的數(shù)據(jù)
這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)只更新部分字段的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
解決mybatis-plus3.1.1版本使用lambda表達(dá)式查詢報(bào)錯(cuò)的方法
這篇文章主要介紹了解決mybatis-plus3.1.1版本使用lambda表達(dá)式查詢報(bào)錯(cuò)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
springboot手動(dòng)動(dòng)態(tài)注入controller和service方式
這篇文章主要介紹了springboot手動(dòng)動(dòng)態(tài)注入controller和service方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
java實(shí)現(xiàn)超市庫(kù)存管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)超市庫(kù)存管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
java實(shí)現(xiàn)畫(huà)圖板上畫(huà)一條直線
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)畫(huà)圖板上畫(huà)一條直線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
IntelliJ IDEA下SpringBoot如何指定某一個(gè)配置文件啟動(dòng)項(xiàng)目
這篇文章主要介紹了IntelliJ IDEA下SpringBoot如何指定某一個(gè)配置文件啟動(dòng)項(xiàng)目問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
JAVA通過(guò)HttpURLConnection 上傳和下載文件的方法
這篇文章主要介紹了JAVA通過(guò)HttpURLConnection 上傳和下載文件的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-09-09
idea與eclipse項(xiàng)目相互導(dǎo)入的過(guò)程(圖文教程)
這篇文章主要介紹了idea與eclipse項(xiàng)目相互導(dǎo)入的過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

