——-android教育訓練java教育訓練期待與您交流!———-
1. 概述
網絡程式設計的本質是兩個裝置之間的資料交換,在計算機網絡中,裝置主要指計算機。
-
網絡模型
網絡傳輸方式中所細緻劃分層次的一個傳輸模型。每個層次都有自己功能作用。

1. OSI參考模型
* 主要有七層定義:兩個裝置間通訊先會進行封裝資訊包的動作然後傳給要傳輸的裝置,接受裝置在進行拆包動作對資訊解析和接受。
2. TCP/IP參考模型
* 是對OSI模型的一個簡化,分為四層。網絡程式設計主要對應的是傳輸層和網際層。
* 傳輸層對應的協定:TCP和UDP。網際層為:IP協定。應用層為HTTP、FTP等等協定。
- 網絡通訊要素
- IP位址:網絡裝置辨別。本機回環IP位址:127.0.0.1或者localhost,也是預設。用途:可以測試網卡等。
- 端口:網絡裝置上應用程式的辨別,此辨別稱作端口(邏輯端口),範圍是0-65535任選,其中0-1024為系統使用或者保留端口。
- 傳輸協定:定義通信規則,此規則稱為協定。常見的協定有:國際通用協定為:TCP/IP,UDP。
package com.sergio.Network;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* IP對象使用示例
* Created by Sergio on 2015-05-19.
*/
public class IPDemo {
public static void main(String[] args) {
InetAddress i = null;
InetAddress ia = null;
try {
i = InetAddress.getLocalHost();
System.out.println(i.toString());
System.out.println(i.getHostAddress());
System.out.println(i.getHostName());
//通過名稱主機名來解析位址和名字。但是還是以ip位址為主
ia = InetAddress.getByName("www.baidu.com");
System.out.println(ia.getHostAddress());
System.out.println(ia.getHostName());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
2. UDP和TCP
- UDP:
- 将資料及源和目的封裝成資料包,不需要建立連接配接
- 每個資料報的大小限制在64k内,有個封包動作
- 因無連接配接,是不可靠協定
- 不需要建立連接配接,速度快
- 應用場景:聊天,視訊,桌面共享等
- TCP:
- 建立連接配接,形成傳輸資料的通道
- 在連接配接中進行大資料量傳輸
- 通過三次握手完成連接配接,是可靠協定
- 必須建立連接配接,效率會稍低
- 應用場景:下載下傳等
3. Socket
- Socket是為網絡服務提供的一種機制
- 通信兩端都有Socket
- 網絡通信就是Socket間的通信
- 資料在兩個Socket間通過IO傳輸
4. UDP應用
- 對應的對象:DatagramSocket與DatagramPacket
- 發送資料的步驟:
- 建立udp socket服務
- 提供資料,并将資料封裝到資料包中
- 通過socket服務的發送功能,将資料包發出去
- 關閉資源
package com.sergio.Network;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* UDP發送資料步驟:
* 1. 建立udp socket服務
* 2. 提供資料,并将資料封裝到資料包中
* 3. 通過socket服務的發送功能,将資料包發出去
* 4。關閉資源
* Created by Sergio on 2015-05-19.
*/
public class UDPSendDataDemo {
public static void main(String[] args) throws Exception {
//socket服務建立
DatagramSocket ds = new DatagramSocket();
//提供資料
byte[] data = "udp send".getBytes();
//封裝資料
DatagramPacket dp =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.123"), );
//發送資料
ds.send(dp);
ds.close();
}
}
- 接收資料的步驟:
- 定義UDP socket服務,通常會監聽一個端口,用來接收該接受的應用程式
- 定義資料包,用來存儲接收到是位元組資料,因為資料包對象中有更多功能可以提取位元組資料的不同資訊,
- 通過socket服務的receive方法将接收到的資料存入一定以好資料包中,
- 通過資料包對象的特有功能,将這些不同的資料取出。
package com.sergio.Network;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* UDP接受資料步驟:
* 1. 定義UDP socket服務,通常會監聽一個端口,用來接收該接受的應用程式
* 2. 定義資料包,用來存儲接收到是位元組資料,因為資料包對象中有更多功能可以提取位元組資料的不同資訊,
* 3. 通過socket服務的receive方法将接收到的資料存入一定以好資料包中,
* 4. 通過資料包對象的特有功能,将這些不同的資料取出。
* Created by Sergio on 2015-05-19.
*/
public class UDPReceiveDataDemo {
public static void main(String[] args) throws Exception {
//建立udp socket服務,指定端口來接受該有的應用程式資訊
DatagramSocket ds = new DatagramSocket();
while (true) {
//定義資料包,用來存儲接受到的資料包
byte[] data = new byte[];
DatagramPacket dp = new DatagramPacket(data, data.length);
//通過服務的receive方法将受到資料存入資料包中
ds.receive(dp);
//通過資料包的方法提取資料資訊
String ip = dp.getAddress().getHostAddress();
//擷取應有長度的資料内容
String data1 = new String(dp.getData(), , dp.getLength());
int port = dp.getPort();
System.out.println(data1 + ip + port);
}
}
}
- 練習聊天:
package com.sergio.Network;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
/**
* 聊天程式
* Created by Sergio on 2015-05-19.
*/
public class ChatDemo {
public static void main(String[] args) throws Exception {
//建立發送和接受對象
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket();
//啟動線程
new Thread(new Send(sendSocket)).start();
new Thread(new Receive(receiveSocket)).start();
}
}
//發送資料端線程
class Send implements Runnable {
private DatagramSocket ds;
public Send(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
//讀取鍵盤錄入并發送資料
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line))
break;
byte[] buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.123"), );
ds.send(dp);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接受資料的線程
class Receive implements Runnable {
private DatagramSocket ds;
public Receive(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
//循環解析資料
while (true) {
byte[] buf = new byte[];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(), , dp.getLength());
System.out.println(ip + "::" + data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. TCP應用
- 對應的對象為:Socket和ServerSocket
-
TCP分用戶端和服務端。用戶端對應的對象為Socket、服務端為:ServerSocket。
步驟:
- 一. 用戶端:
- 建立Socket服務,并指定要連接配接的主機和端口。
- 擷取Socket流的中的輸出流,将資料寫到該流中,通過網絡發送給服務端。
- 關閉Scoket。
- 二. 服務端:
- 建立服務端的Socket服務,ServerSocket();
- 擷取連接配接過來的用戶端對象,通過ServerSocket的accept方法連接配接,此方法是阻塞式的。
- 用戶端如果發來資料,服務端需要使用對應的用戶端對象,并擷取到該用戶端對象的讀取流來讀取發來的資料。
- 關閉服務端(可選)。
- 注意:服務端沒有輸入輸出流,主要是利用用戶端對象的輸出輸入流來讀取資料資訊。
package com.sergio.Network;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 互動式用戶端示例
* Created by Sergio on 2015-05-20.
*/
public class TCPClientDemo2 {
public static void main(String[] args) throws IOException {
//建立Socket服務,指定連接配接主機和端口号
Socket s = new Socket("192.168.1.123", );
//擷取Socket流中的輸出流,并寫入到該流中
OutputStream out = s.getOutputStream();
out.write("互動式資訊發送".getBytes());
//互動部分代碼輸入,讀取資料
InputStream in = s.getInputStream();
byte[] buf = new byte[];
int len = in.read(buf);
System.out.println(new String(buf, , len));
s.close();
}
}
package com.sergio.Network;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 互動式服務端示例
* Created by Sergio on 2015-05-20.
*/
public class TCPServerDemo2 {
public static void main(String[] args) throws IOException {
//建立ServerSocket服務,并監聽10004端口
ServerSocket ss = new ServerSocket();
//通過accept方法擷取用戶端對象
Socket s = ss.accept();
//列印用戶端的ip位址
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "連接配接進來");
//擷取用戶端的輸入流,并讀取資料
InputStream is = s.getInputStream();
byte[] buf = new byte[];
int len = is.read(buf);
System.out.println(new String(buf, , len));
//與用戶端互動部分,寫入資料
OutputStream out = s.getOutputStream();
out.write("服務端受到資訊".getBytes());
s.close();
ss.close();
}
}
- 鍵盤錄入資料服務端傳回大寫格式資訊示例:
package com.sergio.Network;
import java.io.*;
import java.net.Socket;
/**
* 将用戶端發送給服務端的字元轉成大寫。注意讀取鍵盤錄入資料的結束标記換行和回車符。
* Created by Sergio on 2015-05-20.
*/
public class TransClientDemo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.1.123", );
//定義讀取鍵盤資料的流對象
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//定義目的,将資料寫入到socket輸出流,發送給服務端
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//對上一句替換語句//PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
//定義一個socket讀取流,讀取服務端傳回的大寫資訊
BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
if ("over".equals(line))
break;
bw.write(line);
//需要有個回車符結束标記
bw.newLine();
bw.flush();
//對上面三句的替換//pw.print(line);
//讀取服務端傳回的資訊
String str = brIn.readLine();
System.out.println("server::" + str);
}
br.close();
s.close();
}
}
package com.sergio.Network;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 将用戶端發送給服務端的字元轉成大寫。注意讀取鍵盤錄入資料的結束标記換行和回車符。
* Created by Sergio on 2015-05-20.
*/
public class TransServerDemo {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket();
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "連接配接進來");
//讀取socket讀取流中的資料
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//目的socket輸出流将大小資料寫入到socket暑促胡柳,并發送給用戶端
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//PrintWriter pw = new PrintWriter(s.getOutputStream());
String line = null;
while ((line = br.readLine()) != null) {
//pw.print(line.toUpperCase());
bw.write(line.toUpperCase());
bw.newLine();
bw.flush();
}
s.close();
ss.close();
}
}
- 用戶端登入伺服器示例:
package com.sergio.Network;
import java.io.*;
import java.net.Socket;
/**
* 上傳圖檔示例,用戶端
* 步驟:1.服務端點,2.讀取用戶端已有的資料,3.通過Socket輸出流将資料發給服務端,
* 4.讀取服務端發聩資訊,5.關閉
* Created by Sergio on 2015-05-22.
*/
public class UploadPicClient {
public static void main(String[] args) throws Exception {
//用來判斷上傳圖檔的上傳要求
//為空
if (args.length != ) {
System.out.println("請選擇一個jpg格式的圖檔");
return;
}
File file = new File(args[]);
if (file.exists() && file.isFile()) {
System.out.println("該檔案有問題");
return;
}
if (!file.getName().endsWith(".jpg")) {
System.out.println("圖檔格式錯誤");
}
if (file.length() > * * ) {
System.out.println("檔案過大");
return;
}
Socket s = new Socket("192.168.1.123", );
FileInputStream fis = new FileInputStream(file);
OutputStream out = s.getOutputStream();
byte[] buf = new byte[];
int len = ;
while ((len = fis.read(buf)) != -) {
out.write(buf, , len);
}
//告訴服務端資料已經傳完
s.shutdownOutput();
//讀取回報的資訊
InputStream in = s.getInputStream();
byte[] bufIn = new byte[];
int num = in.read(bufIn);
System.out.println(new String(bufIn, , num));
fis.close();
s.close();
}
}
package com.sergio.Network;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 上傳圖檔示例,并發處理服務端
* Created by Sergio on 2015-05-22.
*/
public class UploadPicServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket();
while (true) {
//擷取用戶端連接配接并監聽位址和端口
Socket s = ss.accept();
//啟動服務端并發處理的線程
new Thread(new PicThread(s)).start();
}
}
}
//服務端上傳圖檔線程
class PicThread implements Runnable {
private Socket s;
PicThread(Socket s) {
this.s = s;
}
@Override
public void run() {
//用來重複上傳圖檔計數
int count = ;
String ip = s.getInetAddress().getHostAddress();
try {
System.out.println(ip + "連接配接進來了");
InputStream in = s.getInputStream();
//處理重複上傳判斷和處理
File file = new File(ip + "(" + (count) + ")" + ".jpg");
while (file.exists()) {
file = new File(ip + "(" + (count++) + ")" + ".jpg");
}
//讀取圖檔
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[];
int len = ;
while ((len = in.read(buf)) != -) {
fos.write(buf, , len);
}
//服務端回應用戶端
OutputStream out = s.getOutputStream();
out.write("上傳成功".getBytes());
fos.close();
s.close();
} catch (Exception e) {
throw new RuntimeException(ip + "上傳失敗");
}
}
}
URL和URLConnection
- URL是對底層傳輸層功能封裝的對象。
- URLConnection相當于應用層對URL的功能封裝,更簡便。
1.URL
package com.sergio.Network;
import java.net.MalformedURLException;
import java.net.URL;
/**
* URL對象示例,對網址進行解析
* Created by Sergio on 2015-05-24.
*/
public class URLDemo {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://www.amazon.cn/clouddrive?sf=1&ref_=nav_Photos_Files");
System.out.println("協定" + url.getProtocol());
System.out.println("主機" + url.getHost());
System.out.println("端口" + url.getPort());
System.out.println("路徑" + url.getPath());
System.out.println("檔案" + url.getFile());
System.out.println("查詢" + url.getQuery());
}
}
2.URLConnection
package com.sergio.Network;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* URLConnection對象使用,對連接配接解析并擷取網頁内容。
* Created by Sergio on 2015-05-24.
*/
public class URLConnectionDemo {
public static void main(String[] args) throws IOException {
URL url = new URL("https://www.amazon.cn.");
//應用層URLConnection對象封裝,打開socket流
URLConnection conn = url.openConnection();
System.out.println(conn);
InputStream in = conn.getInputStream();
byte[] buf = new byte[];
int len = in.read(buf);
//列印擷取到的資料資訊
System.out.println(new String(buf, , len));
}
}