[TOC]
# InetAddress
JDK中提供了一個InetAdderss類,該類用于封裝一個IP地址,并提供了一系列與IP地址相關的方法,下表中列出了InetAddress類的一些常用方法

其中,前兩個方法用于獲得該類的實例對象,第一個方法用于獲得表示指定主機的InetAddress對象,第二個方法用于獲得表示本地的InetAddress對象。通過InetAddress對象便可獲取指定主機名,IP地址等
~~~
InetAddress local = InetAddress.getLocalHost();
InetAddress remote = InetAddress.getByName("pv.xinyuntec.com");
System.out.println("本機ip: "+local.getHostAddress());
System.out.println("xinyun的ip: "+remote.getHostAddress());
System.out.println("xinyun的主機: "+remote.getHostName());
~~~
# UDP
UDP是一種面向無連接的協議,因此,在通信時發送端和接收端不用建立連接。UDP通信的過程就像是貨運公司在兩個碼頭間發送貨物一樣。在碼頭發送和接收貨物時都需要使用集裝箱來裝載貨物,UDP通信也是一樣,發送和接收的數據也需要使用“集裝箱”進行打包,為此JDK中提供了一個DatagramPacket類,該類的實例對象就相當于一個集裝箱,用于封裝UDP通信中發送或者接收的數據。
## DatagramPacket
接收方

發送方

使用該構造方法在創建DatagramPacket對象時,不僅指定了封裝數據的字節數組和數據的大小,還指定了數據包的目標IP地址(addr)和端口號(port)。該對象通常用于發送端,因為在發送數據時必須指定接收端的IP地址和端口號,就好像發送貨物的集裝箱上面必須標明接收人的地址一樣。
**常用方法**

## DatagramSocket
DatagramPacket數據包的作用就如同是“集裝箱”,可以將發送端或者接收端的數據封裝起來。然而運輸貨物只有“集裝箱”是不夠的,還需要有碼頭。在程序中需要實現通信只有DatagramPacket數據包也同樣不行,為此JDK中提供的一個DatagramSocket類。DatagramSocket類的作用就類似于碼頭,使用這個類的實例對象就可以發送和接收DatagramPacket數據包,發送數據的過程如下圖所示。

在創建發送端和接收端的DatagramSocket對象時,使用的構造方法也有所不同
常用的構造方法

常用方法

## UDP網絡程序(聊天室)
**接收端**
~~~
//創建數據包傳輸對象,并綁定端口6000
DatagramSocket datagramSocket = new DatagramSocket(6000);
//創建字節數組
byte[] data = new byte[1024];
while (true) {
//創建數據包對象,傳遞字節數組
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
//調用datagramSocket對象方法receive傳遞數據包
datagramSocket.receive(datagramPacket);
//獲取發送端的ip地址對象和端口
String ip = datagramPacket.getAddress().getHostAddress();
int port = datagramPacket.getPort();
int length = datagramPacket.getLength();
System.out.println(new String(data,0,length)+"..."+ip+":"+port);
}
//datagramSocket.close();
~~~
**發送端**
~~~
Scanner sc = new Scanner(System.in);
//創建DatagramSocket對象,數據包的發送和接收對象
DatagramSocket datagramSocket = new DatagramSocket();
//創建InetAddress對象,封裝自己的ip地址
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
while (true) {
String message = sc.nextLine();
byte[] date = message.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(date, date.length, inetAddress, 6000);
//發送數據包
datagramSocket.send(datagramPacket);
}
//關閉資源
//datagramSocket.close();
~~~
# TCP
UDP中只有發送端和接收端,不區分客戶端與服務器端,計算機之間可以任意地發送數據。
而TCP通信是嚴格區分客戶端與服務器端的,在通信時,必須先由客戶端去連接服務器端才能實現通信,服務器端不可以主動連接客戶端,并且服務器端程序需要事先啟動,等待客戶端的連接。
在JDK中提供了兩個類用于實現TCP程序,一個是ServerSocket類,用于表示服務器端,一個是Socket類,用于表示客戶端。
## ServerSocket
使用該構造方法在創建ServerSocket對象時,就可以將其綁定到一個指定的端口號上(參數port就是端口號)。

ServerSocket的常用方法

ServerSocket對象負責監聽某臺計算機的某個端口號,在創建ServerSocket對象后,需要繼續調用該對象的accept()方法,接收來自客戶端的請求。當執行了accept()方法之后,服務器端程序會發生阻塞,直到客戶端發出連接請求,accept()方法才會返回一個Scoket對象用于和客戶端實現通信,程序才能繼續向下執行
## Socket
用于實現TCP客戶端程序
**構造方法**
該構造方法在創建Socket對象時,會根據參數去連接在指定地址和端口上運行的服務器程序,其中參數host接收的是一個字符串類型的IP地址

參數address用于接收一個InetAddress類型的對象,該對象用于封裝一個IP地址。

**常用方法**
| 方法聲明 | 功能描述 |
| --- | --- |
| int getPort() | 該方法返回一個int類型對象,該對象是Socket對象與服務器端連接的端口號 |
| InetAddress getLocalAddress() | 該方法用于獲取Socket對象綁定的本地IP地址,并將IP地址封裝成 InetAddress類型的對象返回 |
| void close() | 該方法用于關閉Socket連接,結束本次通信。在關閉socket之前,應將與socket相關的所有的輸入/輸出流全部關閉,這是因為一個良好的程序應該在執行完畢時釋放所有的資源 |
| InputStream getInputStream() | 該方法返回一個InputStream類型的輸入流對象,如果該對象是由服務器端的Socket返回,就用于讀取客戶端發送的數據,反之,用于讀取服務器端發送的數據 |
| OutputStream getOutputStream() | 該方法返回一個OutputStream類型的輸出流對象,如果該對象是由服務器端的Socket返回,就用于向客戶端發送數據,反之,用于向服務器端發送數據 |
在Socket類的常用方法中,getInputStream()和getOutStream()方法分別用于獲取輸入流和輸出流。當客戶端和服務端建立連接后,數據是以IO流的形式進行交互的,從而實現通信。
接下來通過一張圖來描述服務器端和客戶端的數據傳輸,如下圖所示

## TCP實現文件上傳
* 服務器端
~~~
/*
* 文件上傳 服務器端
*
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//1,創建服務器,等待客戶端連接
ServerSocket serverSocket = new ServerSocket(8888);
Socket clientSocket = serverSocket.accept();
//顯示哪個客戶端Socket連接上了服務器
InetAddress ipObject = clientSocket.getInetAddress();//得到IP地址對象
String ip = ipObject.getHostAddress(); //得到IP地址字符串
System.out.println("小樣,抓到你了,連接我!!" + "IP:" + ip);
//7,獲取Socket的輸入流
InputStream in = clientSocket.getInputStream();
//8,創建目的地的字節輸出流 D:\\upload\\192.168.74.58(1).jpg
BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\upload\\192.168.74.58(1).jpg"));
//9,把Socket輸入流中的數據,寫入目的地的字節輸出流中
byte[] buffer = new byte[1024];
int len = -1;
while((len = in.read(buffer)) != -1){
//寫入目的地的字節輸出流中
fileOut.write(buffer, 0, len);
}
//-----------------反饋信息---------------------
//10,獲取Socket的輸出流, 作用:寫反饋信息給客戶端
OutputStream out = clientSocket.getOutputStream();
//11,寫反饋信息給客戶端
out.write("圖片上傳成功".getBytes());
out.close();
fileOut.close();
in.close();
clientSocket.close();
//serverSocket.close();
}
}
~~~
* 編寫客戶端,完成上傳圖片
~~~
/*
* 文件上傳 客戶端
*
* public void shutdownOutput() 禁用此Socket的輸出流,間接的相當于告知了服務器數據寫入完畢
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
//2,創建客戶端Socket,連接服務器
Socket socket = new Socket("192.168.74.58", 8888);
//3,獲取Socket流中的輸出流,功能:用來把數據寫到服務器
OutputStream out = socket.getOutputStream();
//4,創建字節輸入流,功能:用來讀取數據源(圖片)的字節
BufferedInputStream fileIn = new BufferedInputStream(new FileInputStream("D:\\NoDir\\test.jpg"));
//5,把圖片數據寫到Socket的輸出流中(把數據傳給服務器)
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fileIn.read(buffer)) != -1){
//把數據寫到Socket的輸出流中
out.write(buffer, 0, len);
}
//6,客戶端發送數據完畢,結束Socket輸出流的寫入操作,告知服務器端
socket.shutdownOutput();
//-----------------反饋信息---------------------
//12,獲取Socket的輸入流 作用: 讀反饋信息
InputStream in = socket.getInputStream();
//13,讀反饋信息
byte[] info = new byte[1024];
//把反饋信息存儲到info數組中,并記錄字節個數
int length = in.read(info);
//顯示反饋結果
System.out.println( new String(info, 0, length) );
//關閉流
in.close();
fileIn.close();
out.close();
socket.close();
}
}
~~~
- 基礎
- 編譯和安裝
- scanner類(鍵盤錄入)
- Random類(隨機數)
- 數組
- 方法
- 類
- ArrayList集合
- char與int
- eclipse
- IDEA
- 變量與常量
- 常用API
- String,StringBuffer,StringBuilder
- 正則,Date,DateFormat,Calendar
- 包裝類,System,Math,Arrays,BigInteger,BigDecimal
- 集合,迭代器,增強for,泛型
- List,set,判斷集合唯一
- map,Entry,HashMap,Collections
- 異常
- IO
- File
- 遞歸
- 字節流
- 字符流
- IO流分類
- 轉換流
- 緩沖流
- 流的操作規律
- properties
- 序列化流與反序列化流
- 打印流
- commons-IO
- IO流總結
- 多線程
- 線程池
- 線程安全
- 線程同步
- 死鎖
- lock接口
- ThreadLoad
- 等待喚醒機制
- 線程狀態
- jdbc
- DBUtils
- 連接池DBCP
- c3p0連接池
- 網絡編程
- 多線程socket上傳圖片
- 反射
- xml
- 設計模式
- 裝飾器模式
- web service
- tomcat
- Servlet
- response
- request
- session和cookie
- JSP
- EL
- JSTL
- 事務
- 監聽器Listener
- 過濾器Filter
- json
- linux安裝軟件
- 反射詳解
- 類加載器和注解
- 動態代理
- jedis
- Hibernate
- 簡介
- 創建映射文件
- Hibernate核心配置文件
- 事務和增刪改查
- HibernateUtils
- 持久化對象的三種狀態
- 檢索方式
- query
- Criteria
- SQLQuery
- 持久化類
- 主鍵生成策略
- 緩存
- 事務管理
- 關系映射
- 注解
- 優化
- struts2
- 搭建
- 配置詳解
- Action
- 結果跳轉方式
- 訪問ServletAPI方式
- 如何獲得參數
- OGNL表達式
- valueStack 值棧
- Interceptor攔截器
- spring
- 導包
- IOC和DI
- Bean獲取與實例化
- Bean屬性注入
- spring注解
- 注解分層
- junit整合
- aop
- 動態代理實現
- cglib代理實現
- aop名詞
- spring的aop
- aop-xml詳解
- aop-注解詳解
- 代理方式選擇
- jdbcTemplate
- spring事務管理
- 回滾注意
- 事務傳播屬性
- MyBatis
- MyBatis簡介
- 入門程序
- 與jdbc hibernate不同
- 原始Dao開發
- Mapper動態代理方式
- SqlMapConfig.xml配置文件
- 輸入參數pojo包裝類
- resultMap
- 動態sql
- 一對一關聯
- 一對多
- 整合spring
- 逆向工程
- maven
- maven簡介
- 倉庫
- maven目錄結構
- maven常用命令
- 生命周期
- eclipse中maven插件
- 入門程序
- 整合struct
- 依賴范圍
- 添加插件
- idea配置
- jar包沖突
- 分模塊開發
- 構建可執行的jar包(包含依賴jar包)
- springMVC
- 處理流程
- java面試
- java版本升級
- java1-8版本變更
- java9新特性
- 鎖
- java資料
- idea
- jdk版本切換
- log4j
- 入門實例
- 基本使用方法
- Web中使用Log4j
- spring中使用log4j
- java代碼優化