網路編程
TCP 編程
使用tcp 之前先建立TCP連接,形成傳輸資料的通道,點對點的通信是可靠的,
2,兩個行程:客戶端 服務端
3,在連接中進行大量資料的傳輸
4,傳輸完畢需要釋放建立的連接,效率較低
客戶端:
1,創建socket物件,指明服務器端的ip和埠,
2,獲取一個輸出流用于向服務器端寫入資料,
3,寫出資料
4,關閉資源
UDP
類似于發電報,發出去就完事了!
將資料源封裝成資料包,不需要建立連接,每個資料包大小限制在64k內
資料包:(datagram)網路傳輸的基本單位
我們需要實作的是由客戶端發送資料服務器接收到資料后回應給客戶端表示已成功接收
我們可以由client端寫起:
? 首先我們需要確定發送的位置即需要ip port 用Socket 封裝
? 需要一個輸出流向服務器寫入資料
然后是服務器:
? 服務器有 ServerSocket 指定埠,然后 socket = ss.accept(); 接收;需要一個輸入流來讀取客戶端的內容,接收完成后向客戶端發一個資料表示已經接收到了資料,然后在客戶端列印
package com.kobedu.demo;
import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/**
* 實作TCP網路編程
* 從客戶端發送檔案給服務器,服務端將檔案保存到本地并 回傳“發送成功”到客戶端,
* 并關閉相應的連接
*/
public class Example3 {
/**
* 客戶端:首先我們不難想到,你是要從客戶端向服務器發資料的,所以
* 你得唯一確定一臺服務器,一個服務器上又不止一個行程,是多個行程同時在跑的
* 所以你也要唯一確定行程,也就是說需要ip port
* 用socket 套接字封裝ip port
* 就可以唯一確定你發資料的地點
*/
@Test
public void client(){
InputStream is = null;
InetAddress inet = null;
Socket socket = null;
//需要向服務器寫入
OutputStream os = null;
ByteArrayOutputStream bao = null;
try {
//ip 對應著InetAddress 類的一個物件
inet = InetAddress.getByName("localhost");
//創建了套接字物件,指明了服務器的ip port
socket = new Socket(inet,1024);
// 用于向服務器寫入資料的輸出流
os = socket.getOutputStream();
//is 位元組輸入流用于從檔案中讀取
is = new FileInputStream("picture/nr1.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer);
}
//相當于告訴了服務器他不用等已經沒資料傳了
socket.shutdownOutput();
//接收來自服務器端的反饋,并顯示在控制臺
is = socket.getInputStream();
bao = new ByteArrayOutputStream();
int len2;
byte[] buff2 = new byte[3];
while((len2 = is.read(buff2))!= -1){
bao.write(buff2,0,len2);
}
System.out.println(bao.toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
if (is!=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os!=null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bao!=null) {
try {
bao.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server(){
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
OutputStream os2 = null;
try {
ss = new ServerSocket(1024);
socket = ss.accept();
is = socket.getInputStream();
os = new FileOutputStream("picture/gril2.jpg");
byte[] buff = new byte[1024];
int len ;
while (((len = is.read(buff)) != -1)) {
os.write(buff,0,len);
}
System.out.println("服務器已成功接收資料!");
// 服務器端給客戶端反饋,是否收到
os2 = socket.getOutputStream();
os2.write("照片我已收到,很漂亮,我很滿意!".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
if (os!=null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os2!=null) {
try {
os2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

由上面的圖片可以看出在實作在服務端接收完畢后反饋給客戶端時會出現上面的問題,就是C S 都一直啟動,在關閉時才有資料的接收成功,結合下圖可以看出程式停在某個部分,下面一框出,出現這種問題是因為在這種情況下,客戶端并未給服務器說他傳完了,服務器傻傻地等就出現了這種情況

UDP
udp 編程從技術的角度上講并不像tcp那樣有嚴格意義上的客戶端與服務端,在計算機網路中學過關于網路編程的相關內容udp和tcp都是傳輸層協議,tcp 在端系統之間的通信是可靠的,tcp會事先建立好連接,將要發送的資料包編號,f發的時候會在本地存一份,以防發送失敗,重新發送,所以tcp編程的通信是可靠的但是這種可靠是需要犧牲時間為代價,在計算機網路中深入理解tcp和udp編程后就不難發現,tcp的事先的連接,給資料編號,連接的釋放,在發送端將資料快取,以防在發送的途中丟失資料,重發,他們各有千秋
@Test
public void sender(){
DatagramSocket socket = null;
DatagramPacket packet = null;
InetAddress inet = null;
try {
//
socket = new DatagramSocket();
String str = "這是以UDP的方式發送資料";
byte[] bytes = str.getBytes();
inet = InetAddress.getByName("localhost");//目標地
packet = new DatagramPacket(bytes,0,bytes.length,inet,1024);
//發送資料
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}finally {
if (socket !=null) {
socket.close();
}
}
}
在上面的代碼中我們可以和tcp 編程做比較,這里并沒有向tcp那樣,在客戶端有輸出流向服務器端寫出資料,而是由DatagramPacket 封裝要發送的資料,用套接字的send的方法發送,
@Test
public void receiver(){
DatagramSocket socket = null;
DatagramPacket datagramPacket = null;
try {
socket = new DatagramSocket(1024);
byte[] bytes = new byte[100];
datagramPacket = new DatagramPacket(bytes,0,bytes.length);
//接收資料
socket.receive(datagramPacket);
System.out.println(new String(datagramPacket.getData(),0, datagramPacket.getLength()));
} catch (Exception e) {
e.printStackTrace();
}finally {
if (socket != null) {
socket.close();
}
}
}
套接字
相當于是一個門,,,,
補充:
Tcp 是面向連接到的保證可靠的傳輸協議;通過tcp協議可以得到一個順序誤差錯的資料流,一旦這兩個socket建立起了連接,他們就可以進行雙向的資料傳輸;
udp是一種無連接的協議,每個資料報都是一個獨立的資訊,包括完整的源地址,目標地址;
udp 傳輸資料時是有大小限制的,每個傳輸的資料報必須要限定在64kb之內;
jdk 中的網路類
無論你是在打電話、發送郵件或建立與Internet的連接,地址是基礎, InetAddress類用來封裝我們前面討論的數字式的IP地址和該地址的域名,你通過一個IP主機名與這個類發生作用, IP主機名比它的IP地址用起來更簡便更容易理解,
InetAddress 類內部隱藏了地址數字,
工廠方法
– InetAddress 類沒有明顯的建構式,為生成一個InetAddress物件,必須運用一個可用的工廠方法,
– 工廠方法(factory method)僅是一個類中靜態方法回傳一個該類實體的約定,對于InetAddress,三個方法 getLocalHost( )、getByName( )以及getAllByName( )可以用來創建InetAddress的實體
getLocalHost();方法回傳象征本地主機的InetAddress物件;
getByName();回傳一個傳給它的主機名的InetAddress,
getAllByName();回傳傳入名稱匹配的所有地址類陣列;
UDP 編程補充
1,什么是Datagram? ——資料報是網上傳輸的獨立的資料包,資料報是能夠正確地到達目的地,到達的時間,順序,內容的完整性是沒有保證的;
2,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/497700.html
標籤:Java
上一篇:JAVA抓取百度熱搜榜實時資料
