什么是網(wǎng)絡(luò)編程?
在網(wǎng)絡(luò)通信協(xié)議下,不同計(jì)算機(jī)上運(yùn)行的程序,進(jìn)行的數(shù)據(jù)傳輸。
- 應(yīng)用場(chǎng)景:即時(shí)通信、網(wǎng)游對(duì)戰(zhàn)、金融證券、國(guó)際貿(mào)易、郵件、等等。
不管是什么場(chǎng)景,都是計(jì)算機(jī)跟計(jì)算機(jī)之間通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸。
-
Java中可以使用java.net包下的技術(shù)輕松開發(fā)出常見的網(wǎng)絡(luò)應(yīng)用程序。
總結(jié)
-
什么網(wǎng)絡(luò)編程?
計(jì)算機(jī)跟計(jì)算機(jī)之間通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸。
-
常見軟件架構(gòu)有哪些?
CS/BS
-
通信的軟件架構(gòu)CS1BS的各有什么區(qū)別和優(yōu)缺點(diǎn)
CS:客戶端服務(wù)端模式需要開發(fā)客戶端
BS:瀏覽器服務(wù)端模式不需要開發(fā)客戶端。
CS:適合定制專業(yè)化的辦公類軟件如:IDEA、網(wǎng)游
BS:適合移動(dòng)互聯(lián)網(wǎng)應(yīng)用,可以在任何地方隨時(shí)訪問的系統(tǒng)。
網(wǎng)絡(luò)編程三要素
-
IP
設(shè)備在網(wǎng)絡(luò)中的地址,是唯一的標(biāo)識(shí)。
-
端口號(hào)
應(yīng)用程序在設(shè)備中唯一的標(biāo)識(shí)。
-
協(xié)議
數(shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)囊?guī)則,常見的協(xié)議有UDP、TCP、http、https、ftp。
總結(jié)
-
網(wǎng)絡(luò)編程三要素分別是什么?
IP、端口號(hào)、協(xié)議
-
網(wǎng)絡(luò)編程三要素分別表示什么?
IP:設(shè)備在網(wǎng)絡(luò)中的地址,是唯一的標(biāo)識(shí)
端口號(hào):應(yīng)用程序在設(shè)備中唯一的標(biāo)識(shí)。
協(xié)議:數(shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)囊?guī)則
? 常見的協(xié)議有UDP、TCP、http、https、ftp
IP
全稱:Internet Protocol,是互聯(lián)網(wǎng)協(xié)議地址,也稱IP地址。
是分配給上網(wǎng)設(shè)備的數(shù)字標(biāo)簽。
通俗理解 上網(wǎng)設(shè)備在網(wǎng)絡(luò)中的地址,是唯一的
常見的IP分類為IPV4、IPV6
IPv4
全稱:Internet Protocol version4,互聯(lián)網(wǎng)通信協(xié)議第四版。
采用32位地址長(zhǎng)度,分成4組
IPv6
全稱:Internet Protocol version6,互聯(lián)網(wǎng)通信協(xié)議第六版。
由于互聯(lián)網(wǎng)的蓬勃發(fā)展,IP地址的需求量愈來愈大,而引PV4的模式下IP的總數(shù)是有限的。
采用128位地址長(zhǎng)度,分成8組。 2^128
IPV4的地址分類形式
- 公網(wǎng)地址(萬維網(wǎng)使用)和私有地址(局域網(wǎng)使用)。
- 192.168.開頭的就是私有址址,范圍即為192.168.0.0–192.168.255.255,專門為組織機(jī)構(gòu)內(nèi)部使用,以此節(jié)省1P
特殊IP地址
? 127.0.0.1,也可以是localhost:是回送地址也稱本地回環(huán)地址,也稱本機(jī)IP,永遠(yuǎn)只會(huì)尋找當(dāng)前所在本機(jī)。
InetAddress類
端口號(hào)
? 應(yīng)用程序在設(shè)備中唯一的標(biāo)識(shí)。
? 端口號(hào):由兩個(gè)字節(jié)表示的整數(shù),取值范圍:0~65535
? 其中0~1023之間的端口號(hào)用于一些知名的網(wǎng)絡(luò)服務(wù)或者應(yīng)用。
? 我們自己使用1024以上的端口號(hào)就可以了。
注意:一個(gè)端口號(hào)只能被一個(gè)應(yīng)用程序使用。
協(xié)議
計(jì)算機(jī)網(wǎng)絡(luò)中,連接和通信的規(guī)則被稱為網(wǎng)絡(luò)通信協(xié)議
- OS引參考模型:世界互聯(lián)協(xié)議標(biāo)準(zhǔn),全球通信規(guī)范,單模型過于理想化,未能在因特網(wǎng)上進(jìn)行廣泛推廣
- TCP/IP參考模型(或TCP/IP協(xié)議):事實(shí)上的國(guó)際標(biāo)準(zhǔn)。
OSI參考模型 | TCP/IP 參考模型 | TCP/IP 參考模型各層對(duì)應(yīng)協(xié)議 | 面向哪些 |
---|---|---|---|
應(yīng)用層 | 應(yīng)用層 | HTTP\FTP\Telnet\DNS | |
表示層 | 應(yīng)用層 | HTTP\FTP\Telnet\DNS | |
會(huì)話層 | 應(yīng)用層 | HTTP\FTP\Telnet\DNS | |
傳輸層 | 傳輸層 | TCP\UDP… | 選擇傳輸使用的TCP,UDP協(xié)議 |
網(wǎng)絡(luò)層 | 網(wǎng)絡(luò)層 | IP\ICMP\ARP | 封裝IP |
數(shù)據(jù)鏈路層 | 物理+數(shù)據(jù)鏈路層 | 硬件設(shè)備 010101010101… | 轉(zhuǎn)換成二進(jìn)制利用物理設(shè)備傳輸 |
物理層 | 物理+數(shù)據(jù)鏈路層 | 硬件設(shè)備 010101010101… | 轉(zhuǎn)換成二進(jìn)制利用物理設(shè)備傳輸 |
UDP協(xié)議
用戶數(shù)據(jù)報(bào)協(xié)議(User Datagram Protocol)
UDP是面向無連接通信協(xié)議。
速度快,有大小限制一次最多發(fā)送64K,數(shù)據(jù)不安全,易丟失數(shù)據(jù)
TCP協(xié)議
傳輸控制協(xié)議TCP(Transmission Control Protocol)
TCP協(xié)議是面向連接的通信協(xié)議。
速度慢,沒有大小限制,數(shù)據(jù)安全。
JDP通信程序
UDP通信程序(發(fā)送數(shù)據(jù))
- 找快遞公司 創(chuàng)建發(fā)送端的DatagramSocket對(duì)象
- 打包禮物 數(shù)據(jù)打包(DatagramPacket)
- 快遞公司發(fā)送包裹 發(fā)送數(shù)據(jù)
- 付錢走人 釋放資源
public class SendMessageDemo {
//發(fā)送數(shù)據(jù)通過Socket發(fā)送
public static void main(String[] args) throws IOException {
// 1. 創(chuàng)建Socket
DatagramSocket datagramSocket = new DatagramSocket();
byte buf[] = "Hello Word".getBytes(StandardCharsets.UTF_8);
int offset = buf.length;
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10086;
// 打包數(shù)據(jù),此處需要明確address, port這樣創(chuàng)建的DatagramPacket才可以被發(fā)送
// 否則會(huì)提示 null address || null buffer
// 該構(gòu)造函數(shù)有英文 Constructs a datagram packet for sending packets
DatagramPacket p = new DatagramPacket(buf, offset, address, port);
// 發(fā)送打包的內(nèi)容并關(guān)閉Socket
datagramSocket.send(p);
datagramSocket.close();
}
}
UDP通信程序(接收數(shù)據(jù))
- 找快遞公司 創(chuàng)建接收端的DatagramSocketi對(duì)象
- 接收箱子 接收打包好的數(shù)據(jù)
- 從箱子里面獲取禮物 解析數(shù)據(jù)包
- 簽收走人 釋放資源
public class ReceiveMessageDemo {
public static void main(String[] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket(PORT);
byte[] buf = new byte[1024];
DatagramPacket p = new DatagramPacket(buf, buf.length);
// 該方法是阻塞的
datagramSocket.receive(p);
System.out.println(new String(p.getData(), 0, p.getLength()));
datagramSocket.close();
}
}
發(fā)送與接收都使用到了DatagramSocket、DatagramPacket,DatagramPacket不指定端口號(hào)則代表為接收方,
DatagramSocket 的receive方法也代表了此文接收方。
UDP的三種通信方式
-
單播
以前的代碼就是單播
-
組播
組播地址:
224.0.0.0 ~ 239 - 255.255.255
(其中 224.0.0.0 ~ 224.0.0.255 為預(yù)留的組播地址)
-
廣播
廣播地址:255.255.255.255
TCP通信程序
TCP通信協(xié)議是一種可靠的網(wǎng)絡(luò)協(xié)議,它在通信的兩端各建立一個(gè)Socket對(duì)象
通信之前要保證連接已經(jīng)建立
通過Socket產(chǎn)生IO流來進(jìn)行網(wǎng)絡(luò)通信
綜合練習(xí)
聊天室多發(fā)練習(xí)
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class ChatRoom {
public static void main(String[] args) throws IOException {
System.out.println("Please enter your username:");
Scanner scanner = new Scanner(System.in);
String username = scanner.nextLine();
User user = new User(username);
user.start();
}
}
class User {
private InetAddress group;
private int port;
private String username;
public User(String username) throws UnknownHostException {
this.group = InetAddress.getByName("224.0.0.1");
this.port = 8888;
this.username = username;
}
public void start() throws IOException {
MulticastSocket multicastSocket = new MulticastSocket(this.port);
multicastSocket.joinGroup(this.group);
new Thread(new RunnableTask(multicastSocket, this.username)).start();
System.out.println("Begin Chat...");
Scanner scanner = new Scanner(System.in);
while (true) {
String messages = scanner.nextLine();
messages = this.username + ":" + messages;
byte[] buf = messages.getBytes(StandardCharsets.UTF_8);
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, this.port);
multicastSocket.send(packet);
}
}
}
class RunnableTask implements Runnable {
private MulticastSocket multicastSocket;
private String username;
public RunnableTask(MulticastSocket multicastSocket, String username) {
this.multicastSocket = multicastSocket;
this.username = username;
}
@Override
public void run() {
byte[] bytes = new byte[1024];
while (true) {
try {
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
multicastSocket.receive(packet);
String userNameAndMessage = new String(packet.getData(), 0, packet.getLength());
if (userNameAndMessage.contains(this.username)) {
continue;
}
System.out.println(userNameAndMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
TCP 文件傳輸練習(xí)
注意點(diǎn):客戶端/服務(wù)端 發(fā)送完數(shù)據(jù)需要通過socket關(guān)閉OutPut,為了增加讀寫效率使用了Buffered流
客戶端
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10000);
File file = new File("D:\\Program Files\\IdeaProjects\\mysocketnet\\clientdir\\1.png");
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
OutputStream outputStream = socket.getOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
// 數(shù)據(jù)緩沖區(qū)
byte[] bytes = new byte[1024];
int len;
while ((len = bufferedInputStream.read(bytes)) != -1) {
// 緩沖區(qū)最后一次的長(zhǎng)度可能不是1024,需要通過InputStream.read 確定
bufferedOutputStream.write(bytes, 0, len);
}
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
System.out.println(bufferedReader.readLine());
socket.close();
}
}
服務(wù)端文章來源:http://www.zghlxwxcb.cn/news/detail-447584.html
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10000);
ExecutorService executorService = Executors.newCachedThreadPool();
while (true) {
Socket socket = serverSocket.accept();
executorService.submit(new MyRunnable(socket));
}
// serverSocket.close();
}
}
自定義任務(wù)文章來源地址http://www.zghlxwxcb.cn/news/detail-447584.html
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class MyRunnable implements Runnable {
Socket socket;
public MyRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream inputStream = null;
try {
inputStream = this.socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
String replace = UUID.randomUUID().toString().replace("-", "");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("D:\\Program Files\\IdeaProjects\\mysocketnet\\serverdir\\" + replace + ".png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] bytes = new byte[1024];
int read = 0;
// inputStream.read 會(huì)一致讀取,直到socket發(fā)送了shutdownOutput
while (true) {
try {
if ((read = inputStream.read(bytes)) != -1) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
try {
fileOutputStream.write(bytes, 0, read);
} catch (IOException e) {
e.printStackTrace();
}
}
OutputStream outputStream = null;
try {
outputStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
String message = "數(shù)據(jù)接受完畢";
try {
outputStream.write(message.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
到了這里,關(guān)于Java網(wǎng)絡(luò)編程(UDP、TCP)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!