UDP-TCP


一.網絡相關基本概念

1.網絡通信協議:是一種網絡通用語言,爲連接不同操作系統和不同硬件體系結構的互聯網絡引提供通信支持,是一種網絡通用語言.通信協議的具體種類有很多,主要有:UDP協議和T CP協議

2.UDP協議:是User Datagram Protocol的簡稱, 中文名是用戶數據報協議.是一種無連接的協議。傳輸效率很高;數據不安全,容易丟失;

特點:

1:面向無連接;

2:效率高;

3:不安全;

3.TCP/IP協議:Transmission Control Protocol/Internet Protocol的簡寫,中譯名爲傳輸控制協議/因特網互聯協議

特點:

1:面向連接;(客戶端和服務器需要事先建立起連接,才能通信,3次握手)

2:效率低;

3:數據安全;

4.網絡協議數據傳輸流程:從下至上:鏈路層--網絡層--傳輸層--應用層

鏈路層:軟件驅動與硬件接口;

網絡層:數據的分組與處理,IP地址,端口號;

傳輸層:網絡通信協議的核心,數據通過網絡進行傳輸;

應用層:應用級軟件,主要進行數據的解析;

5.IP地址:是網絡中的參與者的唯一身份標識.包含IPV4/IPV6.IPV4使用4個字節表示IP地址;每個字節的範圍只能是0-255之間.

6.端口號:是電腦中用於識別不同進程;用2個字節表示一個端口號,能表示的範圍0-65535(2^16=65536);其中0-1024端口號已經被計算機的核心服務佔用了,建議程序員使用1024之後

的端口號.


二.InetAddress 類(java.net)

介紹:InetAddress是java編寫的一個類,用於描述計算機的ip地址;

構造方法:InetAddress構造方法不能直接使用,因此必須通過靜態方法,獲取對象:

繼承關係:java.lang.Object--java.net.InetAddress

定義:public class InetAddress extends Object implements Serializable

靜態方法:

public static InetAddress getByName(String host){}:在給定主機名的情況下確定主機的 IP 地址

public static InetAddress getLocalHost() throws UnknownHostException{}:返回本地主機

常用方法:

public String getHostAddress(){}:返回 IP 地址字符串(以文本表現形式)

public String getHostName(){}:獲取此 IP 地址的主機名

代碼演示:

import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetDemo{
public static void main(String[] args){
//獲取本地主機,返回InetAddress對象
InetAddress host = null;
try{
host = InetAddress.getLocalHost();
}catch(UnknownHostException e){
e.printStackTrace();
}
System.out.println(host);
//獲取本地主機名
String name = host.getHostName();
//獲取本地ip
String ip = host.getHostAddress();
System.out.println("計算機名:"+name+";ip爲:"+ip);
//通過別人的計算機名,獲取別人計算機的IP
try{
host = InetAddress.getByName("LWL");
}catch(UnknownHostException e){
e.printStackTrace();
}
String ip1 = host.getHostAddress();
System.out.println(ip1);
}
}


二.UDP 常用類

1.DatagramPacket 類(java.net)

繼承關係:java.lang.Object--java.net.DatagramPacket

定義:public final class DatagramPacket extends Object

構造方法:

DatagramPacket(byte[] buf, int length, InetAddress address, int port):構造數據報包,用來將長度爲 length 的包發送到指定主機上的指定端口號。

Buf:數組,用於保存要發送的數據;

Length:要發送的數據的長度;

Address:接收者的ip地址對象;

Port:接收者的端口號;

(這個對象用在發送端).

DatagramPacket(byte[] buf, int length):構造 DatagramPacket,用來接收長度爲 length 的數據包。

Buf:發送者發送的數據將會保存到buf數組中;

Length:表示這個DatagramPacket對象的數組,有多少個位置可以使用;

(這個對象用在接收端).

常用主法:

public byte[] getData(){}:Returns the data buffer. The data received or the data to be sent starts from the offset in the buffer, and runs for length 

long.

public int getLength(){}: Returns the length of the data to be sent or the length of the data received.


2.DatagramSocket 類(java.net)

繼承關係:java.lang.Object--java.net.DatagramSocket

定義:public class DatagramSocket extends Object implements Closeable

構造方法:

DatagramSocket()  throws SocketException:構造數據報套接字並將其綁定到本地主機上任何可用的端口。

(一般將該對象用在發送端,可以通過該對象,將數據報包對象發送出去)

DatagramSocket(int port) : 創建數據報套接字並將其綁定到本地主機上的指定端口。(一般用在接收端,監聽指定的端口號,可以接收別人向該端口發送的數據報包)

常用方法:

public void send(DatagramPacket p) throws IOException{}:從此套接字發送數據報包

public void receive(DatagramPacket p) throws IOException{}:從此套接字接收數據報包。

該方法有線程阻塞的效果,因此必須在接收端先調用該方法,發送端才能發數據報包,否則會丟失數據報包


3.UDP通信案例

//UDP通信實現:Receiver
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceiver {
public static void main(String[] args) throws Exception {
// 準備用於接收的數據報包對象
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b, b.length);
// 創建接收端對象
DatagramSocket ds = new DatagramSocket(8891);
// 接收端使用自己的數據報包對象接收發送過來的數據
ds.receive(dp);
// 獲取數組和有效長度
byte[] bs = dp.getData();
int i = dp.getLength();
// 轉字符串
String s = new String(bs, 0, i);
System.out.println("發送端說:" + s);
ds.close();
}
}
//UDP通信實現:sender
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class UDPSender {
public static void main(String[] args) throws Exception {
// 提示發送者輸入發送消息
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要發送的消息::");
String message = sc.next();
// 將輸入的消息轉化成字節數組
byte[] b = message.getBytes();
// 將原始數據封裝成DatagramPacket對象
DatagramPacket dp = new DatagramPacket(b, b.length,InetAddress.getLocalHost(), 8891);
// 創建發送端對象
DatagramSocket ds = new DatagramSocket();
// 使用發送端對象將封裝的DatagramPacket對象發送出去
ds.send(dp);
// 關閉流
ds.close();
}
}




三.TCP 常用類

1.Socket

介紹:用於表示客戶端的一個類.TCP 協議中客戶端和服務器的交互是通過IO流完成的,而所有的 IO 流對象都是客戶端提供的!

繼承關係:java.lang.Object--java.net.Socket

定義:public class Socket extends Object implements Closeable

構造方法:

Socket(String host, int port) throws UnknownHostException,IOException :創建一個流套接字並將其連接到指定主機上的指定端口號。如果該客戶端對象能創建成功,說明3次握手已經成功了!


2.ServerSocket

介紹:用於表示服務端的一個類

繼承關係:java.lang.Object--java.net.ServerSocket

定義:public class ServerSocket extends Object implements Closeable

構造方法:

ServerSocket(int port) throws IOException : 創建綁定到特定端口的服務器套接字。實際開發中先有服務器對象,纔會有客戶端去訪問;因此創建服務器對象的人,可以自己指定一個端口號;

常用方法:

public Socket accept() throws IOException{}: 偵聽並接受到此套接字的連接。該方法有線程阻塞的效果,如果沒有客戶端訪問該服務器,那麼該服務器的當前線程將一直阻塞


3.TCP 通信案例

//客戶端
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class TCPClientDemo {
public static void main(String[] args) throws UnknownHostException,
IOException {
// 創建客戶端對象
Socket s = new Socket("127.0.0.1", 9999);
// 面對客戶端對象獲取網絡中的輸出流
OutputStream out = s.getOutputStream();
// 向網絡中寫入數據
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要發送的消息:");
String str = sc.next();
out.write(str.getBytes());
}
}


//服務器端
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPReceiverDemo {
public static void main(String[] args) throws IOException {
// 創建服務器端對象
ServerSocket ss = new ServerSocket(9999);
// 讓服務器端對象等待客戶端連接 accept
Socket s = ss.accept();
// 面向Socket對象,獲取輸入流對象
InputStream in = s.getInputStream();
// 一次讀完
byte[] b = new byte[1024];
int i = in.read(b);
// 轉換成字符串輸出
String str = new String(b, 0, i);
System.out.println("客戶端發來消息:" + str);
}
}

4.文件上傳案例多線程版

/*
 文件上傳服務器端 多線程
 */
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileloadServer {
public static void main(String[] args) throws Exception {
// 創建服務器端對象
ServerSocket ss = new ServerSocket(8870); // throws IOException
// 監聽端口,形成阻塞狀態
while (true) {
final Socket s = ss.accept();// throws IOException
new Thread() {
@Override
public void run() {
try {
// 我是服務器中的程序,我要創建一個本地的寫入流 網絡輸入流--本地輸出流--本地文件
InputStream in = s.getInputStream();
FileOutputStream fout = new FileOutputStream(
System.currentTimeMillis() + ".jpg");
// 我是服務器中的程序,我要讀取客戶端發過來的信息
int i = -1;
byte[] b = new byte[1024];
while ((i = in.read(b)) != -1) {
fout.write(b, 0, i); // 寫入本地磁盤
}
// 通知客戶端上傳成功
OutputStream out = s.getOutputStream();
out.write("上傳成功".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
}
/*
 上傳文件客戶端
 */
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class FileUploadClient {
public static void main(String[] args) throws Exception {
// 創建本地文件的輸入流 我是程序:本地文件--本地文件輸入流--網絡輸出流
FileInputStream fin = new FileInputStream("E:\\JAVAPractice\\net\\1.jpg");// throws FileNotFoundException
// 創建客戶端對象
Socket s = new Socket("127.0.0.1", 8870);// throws UnknownHostException,IOException
// 面向客戶端 獲取輸出流
OutputStream out = s.getOutputStream(); // throws IOException
// 循環 寫入網絡
int i = -1;
byte[] b = new byte[1024];
while ((i = fin.read(b)) != -1) {
out.write(b, 0, i);
}
// 通知服務器端循環輸出完成--解決死鎖問題
s.shutdownOutput(); // throws IOException
// 若文件上傳完成,需通知客戶端
InputStream in = s.getInputStream();// throws IOException
i = in.read(b);
String message = new String(b, 0, i);// Throws IndexOutOfBoundsException
System.out.println("消息來自服務端:" + message);
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章