IP:網路定位的唯一一台主機,Java中表示 IP 地址,為 InetAddress 類;
分為IPv4(例如 192.168.0.1)、IPv6(例如 3ffe:3201:1401:1280:c8ff:fe4d:db39:1984);私有IP地址(局部網域)範圍即為192.168.0.0 ~ 192.168.255.255
Port 號:定位主機上哪一個應用程序(Process)在執行;Port 號用來區分一台主機上的不同應用程序的 Process
domain(域名):在 browser 輸入域名,透過DNS(域名解析服務器)取得實際IP地址後、連接實際的Web server
網路通信協議分層思想:
可靠的
進行大資料量的傳輸
釋放已建立的連接,效率低
不需要建立連接
不可靠的
無需釋放資源,開銷小,速度快
@Test
public void inetAddressTest() {
try {
// 取得域名IP
InetAddress google = InetAddress.getByName("www.google.com");
System.out.println(google);
// 取得域名
System.out.println(google.getHostName());
// 取得IP地址
System.out.println(google.getHostAddress());
// 取得本機IP
InetAddress host1 = InetAddress.getLocalHost();
System.out.println(host1);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
**
* 實現TCP網路編程
* @author sunwc
* @create 2023-04-02 下午 02:37
*/
public class SocketTest {
/**
* 模擬客戶端
*/
@Test
public void client() {
Socket socket = null;
OutputStream os = null;
try {
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
// 創建Socket物件,指明服務器端的IP與port號
socket = new Socket(inetAddress, 8899);
// 取得輸出流,用於輸出資料
os = socket.getOutputStream();
// 寫出資料
os.write("你好,這邊是客戶端".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 模擬服務器端
*/
@Test
public void server() {
ByteArrayOutputStream baos = null;
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
try {
// 創建服務器端的ServerSocket,指名自己的port號
serverSocket = new ServerSocket(8899);
// 接收客戶端的Socket
socket = serverSocket.accept();
// 取得輸入流
is = socket.getInputStream();
// 暫時用baos儲存所有bytes
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[20];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
System.out.println("收到來自 客戶端:" + socket.getInetAddress().getHostAddress() + "的資料");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.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 (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
**
* 從客戶端發送文件給服務器端,服務器端保存文件至本地,並回傳“發送成功”給客戶端
* @author sunwc
* @create 2023-04-02 下午 04:30
*/
public class TCPTest {
@Test
public void client() throws IOException {
// 1. 建立客戶端Socket
Socket socket = new Socket("127.0.0.1", 9090);
// 2. 取得輸入流讀取本地文件
FileInputStream fis = new FileInputStream("girl.png");
// 3. 取得輸出流
OutputStream os = socket.getOutputStream();
// 4. 進行讀寫操作
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 5. socket關閉資料的輸出
socket.shutdownOutput();
// 6. 接收來自於服務器端的反饋,將資料顯示在console上
// 考量接收的訊息輸出的console可能有亂碼問題,故使用ByteArrayOutputStream
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
buffer = new byte[20];
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
// 7. 關閉資源
baos.close();
is.close();
os.close();
fis.close();
socket.close();
}
@Test
public void server() throws IOException {
// 1. 建服務器Socket
ServerSocket ss = new ServerSocket(9090);
// 2. 接收客戶端Socket
Socket socket = ss.accept();
// 3. 取得輸入流
InputStream is = socket.getInputStream();
// 4. 準備輸出流:將從客戶端取得的圖片寫至本地
FileOutputStream fos = new FileOutputStream("girl_final.png");
// 5. 讀寫操作
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("服務器端圖片寫出完成");
// 6. 服務器端給予客戶端反饋
OutputStream os = socket.getOutputStream();
os.write("您好,服務器端有收到您傳過來的圖片了".getBytes(StandardCharsets.UTF_8));
// 7.關閉資源
os.close();
fos.close();
is.close();
socket.close();
ss.close();
}
}
/**
* 客戶端給服務端發送txt文件,服務端將文件轉成大寫再回傳給客戶端
* @author sunwc
* @create 2023-04-02 下午 05:39
*/
public class TCPTest2 {
@Test
public void client() throws IOException {
// 1. 建立與服務器端連接的socket
Socket socket = new Socket("127.0.0.1",9999);
// 2. 讀取本地文件並暫時保存在 ByteArrayOutputStream
FileInputStream fis = new FileInputStream("english.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 3. 取得輸出流
OutputStream os = socket.getOutputStream();
byte[] buffer = new byte[20];
int len;
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
// 4. 一次性寫出資料到服務器端
os.write(baos.toByteArray());
// 5. socket關閉輸出資料
socket.shutdownOutput();
// 6. 取得服務器端大寫英文字的資料並將資料寫到本地文件
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("english_final.txt");
buffer = new byte[20];
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
// 7. 關閉資源
fos.close();
is.close();
os.close();
baos.close();
fis.close();
socket.close();
}
@Test
public void server() throws IOException {
// 1. 建立服務器端socket
ServerSocket ss = new ServerSocket(9999);
// 2. 接收客戶端socket
Socket socket = ss.accept();
// 3. 接收輸入流並將資料暫時寫入 ByteArrayOutputStream
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[20];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println("服務器端文件接收完成");
// 4. 將 ByteArrayOutputStream 資料一次性將英文字轉大寫
String upperCase = baos.toString().toUpperCase(Locale.ROOT);
// 5. 一次性寫出大寫英文字資料到客戶端
OutputStream os = socket.getOutputStream();
os.write(upperCase.getBytes(StandardCharsets.UTF_8));
System.out.println("服務器端文件轉大寫並傳輸完成");
// 6. 關閉資源
os.close();
baos.close();
is.close();
socket.close();
ss.close();
}
}