TCP和UDP協(xié)議是TCP/IP協(xié)議的核心。 TCP 傳輸協(xié)議:TCP 協(xié)議是一TCP (Transmission Control
Protocol)和UDP(User Datagram
Protocol)協(xié)議屬于傳輸層協(xié)議。其中TCP提供IP環(huán)境下的數(shù)據(jù)可靠傳輸,它提供的服務包括數(shù)據(jù)流傳送、可靠性、有效流控、全雙工操作和多路復用。通過面向連接、端到端和可靠的數(shù)據(jù)包發(fā)送。通俗說,它是事先為所發(fā)送的數(shù)據(jù)開辟出連接好的通道,然后再進行數(shù)據(jù)發(fā)送;而UDP則不為IP提供可靠性、流控或差錯恢復功能。一般來說,TCP對應的是可靠性要求高的應用,而UDP對應的則是可靠性要求低、傳輸經(jīng)濟的應用
1. 基于TCP的網(wǎng)絡編程
IP是一個通信實體在網(wǎng)絡上的地址,通信實體可以是打印機、計算機等。IP協(xié)議的作用是讓Internet成為一個允許連接不同類型計算機和不同操作系統(tǒng)的網(wǎng)絡。IP協(xié)議負責將消息從一個主機傳到另一個主機,消息在傳遞過程中被分割成小包。但是IP協(xié)議不能解決數(shù)據(jù)包在傳輸過程中遇到的問題,所以計算機需要TCP協(xié)議來保證傳輸?shù)目煽啃浴?br> TCP叫端對端協(xié)議,當一臺計算機要與另一臺遠程計算機進行通信時,TCP在兩臺計算機之間建立一個連接,用于發(fā)送和接收數(shù)據(jù)。TCP協(xié)議負責將數(shù)據(jù)包按一定順序放好并發(fā)送,接收端在按照正確的順序排列數(shù)據(jù)包。TCP提供了一個重發(fā)機制,當一個通信實體A發(fā)送消息給通信實體B后,A需要收到B的確認信息,如果沒有收到B的確認信息,A會重新發(fā)送信息。
凡是在Internet上的計算機都必須安裝IP協(xié)議和TCP協(xié)議,這兩個協(xié)議統(tǒng)稱TCP/IP協(xié)議。 TCP的三次握手
a.客戶端向服務端發(fā)送一個請求 b.服務端收到請求后,回客戶端一個響應 c.客戶端向收到服務端的響應后,回服務端一個確認信息
1.1 ServerSocket創(chuàng)建服務端
ServerSocket用于監(jiān)聽來自客戶端的Socket連接。如果沒有連接,它將處于等待狀態(tài)。 ServerSocket中常用方法:
Socket accept():如果接收到一個客戶端Socket連接請求,該方法返回一個客戶端對應的Socket對象。
ServerSocket(int port):用戶指定端口port來創(chuàng)建一個ServerSocket,端口在1~65535之間。
close():用于關閉服務端。
public class Server {
public static void main(String[] args) {
// 1.實例化一個ServerSocket的對象
ServerSocket serverSocket = null;
OutputStream output = null;// 用于向別人發(fā)消息
InputStream input = null;// 用于讀取別人發(fā)過來的消息
try {
serverSocket = new ServerSocket(8888);
System.out.println("等待服務端的連接...");
// 2.監(jiān)聽,獲取連接到的客戶端 注意:在未連接成功之前,將一直處于阻塞狀態(tài)
Socket socket = serverSocket.accept();
System.out.println("連接成功");
// 3.獲取網(wǎng)絡到內(nèi)存的一個輸入流
input = socket.getInputStream();
// 4.讀取數(shù)據(jù),這個數(shù)據(jù)是Client發(fā)過來的
byte[] arr = new byte[1024];
int len = input.read(arr);
String message = new String(arr, 0, len);
// 5.組織信息
String ipString = socket.getInetAddress().getHostAddress();
int port = socket.getPort();
System.out.println(ipString + ":" + port + "說:" + message);
// 6.服務端給客戶端回復消息
output = socket.getOutputStream();
output.write("你也好,好久不見了".getBytes());
output.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
output.close();
input.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服務端不應該只接受一個客戶端請求后就停止,所以在程序中可以通過循環(huán)不斷的調(diào)用accept()方法:
while(true){
Socket socket=serverSocket.accept();
}
1.2 Socket創(chuàng)建客戶端
客戶端可以使用Socket構造器連接指定的服務端。
public class Client {
public static void main(String[] args) {
Socket socket = null;// 1.建立一個與服務端之間的連接
OutputStream output = null;// 用于向別人發(fā)消息
InputStream input = null;// 用于讀取別人發(fā)過來的消息
try {
socket = new Socket("127.0.0.1", 8888);
// 2.將需要發(fā)送的數(shù)據(jù)寫入到網(wǎng)絡中,注意:包含了兩個流:InputStream和OutputStream
output = socket.getOutputStream();
output.write("hello你好嗎?".getBytes());// 3.寫入
output.flush();
// 4.收取服務端發(fā)送來的消息 new BufferedInputStream(socket.getInputStream());
input = socket.getInputStream();
byte[] arr = new byte[1024];
int len = input.read(arr);
String message = new String(arr, 0, len);
System.out.println("來自服務端的回復:" + message);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
output.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.3 加入多線程
使用多線程實現(xiàn)客戶端和服務端持續(xù)會話:
public class ServerThread extends Thread {
private Socket client;
public ServerThread() {
}
public ServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
OutputStream output = null;
InputStream input = null;
try {
output = client.getOutputStream();
input = client.getInputStream();
// 從控制臺進行獲取數(shù)據(jù)
Scanner scanner = new Scanner(System.in);
// 進行循環(huán)的發(fā)送和接收消息
while (true) {
byte[] arr = new byte[1024];// 接收客戶端發(fā)送來的消息
int len = input.read(arr);
String message = new String(arr, 0, len);
System.out.println("來自客戶端的消息:" + message);
System.out.println("服務端對客戶端說:");
String reply = scanner.nextLine();// 回復消息
output.write(reply.getBytes());
output.flush();
if (message.equals("886") || message.equals("bye") || message.equals("再見")) {// 約定
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
output.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8888);
while (true) {
Socket socket = serverSocket.accept();
ServerThread thread = new ServerThread(socket);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;// 1.建立一個與服務端之間的連接
OutputStream output = null;// 用于向別人發(fā)消息
InputStream input = null;// 用于讀取別人發(fā)過來的消息
Scanner scanner = new Scanner(System.in);
try {
socket = new Socket("127.0.0.1", 8888);
output = socket.getOutputStream();
input = socket.getInputStream();
while (true) {
System.out.println("客戶端對服務端說:");
String message = scanner.nextLine();
output.write(message.getBytes());// 進行發(fā)送
output.flush();
byte[] arr = new byte[1024];// 接收消息
int len = input.read(arr);
String reply = new String(arr, 0, len);
System.out.println("收到服務端的反饋:" + reply);
if (reply.equals("886") || reply.equals("bye") || reply.equals("再見")) {// 約定
break;
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
output.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2. 基于UDP的編程
UDP是User Datagram
Protocol的簡稱,用戶數(shù)據(jù)報協(xié)議,它不管對方是否在線,直接向對方發(fā)送數(shù)據(jù),至于對方能否收到,UDP無法控制,所以它是一種簡單不可靠的協(xié)議。適用于一次傳輸量較少,對可靠性要求不高的情景。
特點:
a.不安全
b.無連接
c.效率高
d.UDP傳輸數(shù)據(jù)時是有大小限制的,每個被傳輸?shù)臄?shù)據(jù)報必須限定在64KB之內(nèi)文章來源:http://www.zghlxwxcb.cn/news/detail-402059.html
public class Receiver {
public static void main(String[] args) {
// 1.實例化DatagramSocket的對象,需要進行綁定端口號:由發(fā)送方發(fā)送來的端口號進行決定
DatagramSocket socket = null;
try {
socket = new DatagramSocket(6666);
// 2.將接收到的數(shù)據(jù)封裝到數(shù)據(jù)報包中,用來接收長度為 length 的數(shù)據(jù)包。
byte[] arr = new byte[4096];
DatagramPacket packet = new DatagramPacket(arr, arr.length);
System.out.println("等待接收數(shù)據(jù)~~~~~~~");
// 3.接收數(shù)據(jù)
// 注意:將數(shù)據(jù)從網(wǎng)絡中讀取出來
socket.receive(packet);
// 4.獲取發(fā)送方的詳細信息
byte[] messages = packet.getData();
String result = new String(messages, 0, packet.getLength());
// 獲取發(fā)送方的ip地址
// 返回某臺機器的 IP 地址,此數(shù)據(jù)報將要發(fā)往該機器或者是從該機器接收到的。
InetAddress address = packet.getAddress();
String ip = address.getHostAddress();
// 獲取消息是從發(fā)送發(fā)的哪個端口號發(fā)出來的
int port = packet.getPort();
System.out.println(ip + ":" + port + "說:" + result.trim());
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
socket.close();
}
}
}
public class Sender {
public static void main(String[] args) {
// 端口號表示的是指定的接收方的端口號,而發(fā)送方的端口是由系統(tǒng)自動分配的
sendMessage("127.0.0.1", 6666, "你好啊");
}
public static void sendMessage(String ip, int port, String message) {
// 1.實例化DatagramSocket的對象, 注意:和流的使用類似,使用套接字完成之后需要關閉
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
// 2.構造數(shù)據(jù)報包,用來將長度為 length 的包發(fā)送到指定主機上的指定端口號。
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, InetAddress.getByName(ip),
port);
// 3.發(fā)送,將數(shù)據(jù)寫入網(wǎng)絡的過程,void send(DatagramPacket p) 從此套接字發(fā)送數(shù)據(jù)報包。
socket.send(packet);
} catch (SocketException e) {
// 父類為IOException
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
socket.close();
}
}
}
傳輸控制協(xié)議(TCP):TCP(傳輸控制協(xié)議)定義了兩臺計算機之間進行可靠的傳輸而交換的數(shù)據(jù)和確認信息的格式,以及計算機為了確保數(shù)據(jù)的正確到達而采取的措施。協(xié)議規(guī)定了TCP軟件怎樣識別給定計算機上的多個目的進程如何對分組重復這類差錯進行恢復。協(xié)議還規(guī)定了兩臺計算機如何初始化一個TCP數(shù)據(jù)流傳輸以及如何結束這一傳輸。TCP最大的特點就是提供的是面向連接、可靠的字節(jié)流服務。
用戶數(shù)據(jù)報協(xié)議(UDP):UDP(用戶數(shù)據(jù)報協(xié)議)是一個簡單的面向數(shù)據(jù)報的傳輸層協(xié)議。提供的是非面向連接的、不可靠的數(shù)據(jù)流傳輸。UDP不提供可靠性,也不提供報文到達確認、排序以及流量控制等功能。它只是把應用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們能到達目的地。因此報文可能會丟失、重復以及亂序等。但由于UDP在傳輸數(shù)據(jù)報前不用在客戶和服務器之間建立一個連接,且沒有超時重發(fā)等機制,故而傳輸速度很快。文章來源地址http://www.zghlxwxcb.cn/news/detail-402059.html
到了這里,關于TCP和UDP網(wǎng)絡編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!