javaSE (四十)網路程式設計(TCP傳輸、伺服器多執行緒、網路程式設計練習:反轉字串、上傳檔案)
阿新 • • 發佈:2018-12-16
1、TCP傳輸:
1.客戶端
- 建立Socket連結服務端(指定ip地址,埠號),通過ip地址找到對應的伺服器
- 呼叫Socket的getInputStream和getOutputStream方法獲取和伺服器端相連的IO流
2.伺服器端
- 建立ServerSocket(指定埠號)
- 呼叫ServerSocket的accept方法接收一個客戶端請求,得到一個Socket
- 呼叫Socket的getInputStream和getOutputStream方法獲取和客戶器端相連的IO流
注:這裡按照上面的步驟就可以通訊了,然後我們用bufferedReader和printStream包裝一下getInputStream和getOutputStream(具體如圖所示,應該很簡潔明瞭)
測試程式碼如下(要先開服務端):
Tcp_client
package SocketCollection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Tcp_client {
public static void main( String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1",12345);
BufferedReader bre = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("我是小雨,我愛你,你愛我麼?" );
System.out.println(bre.readLine());
socket.close;
}
}
Tcp_server
package SocketCollection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcp_server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(12345);
Socket socket = server.accept();
BufferedReader bre = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
System.out.println(bre.readLine());
ps.println("我是阿倫,我也愛你!");
socket.close;
}
}
效果如圖:
2、伺服器多執行緒:
簡單地將伺服器端改為多執行緒,應對更多的請求
思路:
- while迴圈
- 匿名內部類,來一個請求就開一個執行緒
修改服務端程式碼如下:
Tcp_server
package SocketCollection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcp_server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(12345);
while (true) {
final Socket socket = server.accept();
new Thread() {
public void run() {
try {
BufferedReader bre = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
System.out.println(bre.readLine());
ps.println("我是阿倫,我也愛你!");
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
}
3、網路程式設計練習:
練習1:客戶端鍵入字串,伺服器端反轉傳回,客戶端接收反轉後的字串
思路:
- 反轉嘛,就想到了StringBuilde.reverse()
- 然後客戶端傳過來用SB接收反轉一下再傳回去就行了
程式碼如下:
Tcp_client
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要反轉的字串:");
String line = sc.nextLine();
Tcp_server
String line = bre.readLine();
StringBuilder sb = new StringBuilder(bre.readLine());
ps.println(sb.reverse().toString());
效果如圖:
練習二:上傳檔案
思路:
- 客戶端鍵入字串,驗證是否為檔名
- 客戶端傳送檔名到伺服器端
- 伺服器建立資料夾存放此檔案(可選),驗證伺服器端是否有此檔案並返回驗證結果
- 客戶端接收結果,若存在,程式停止,若不存在,上傳檔案(IO流FileInputStream /FileOutputStream)
- 伺服器端接收檔案(傳的是檔案的byte[]流),並寫入(在自己電腦上實驗可以寫到本地,也就是當前工程目錄下)
(和之前的IO流不同的是,這裡需要經過socket.getOutputStream()和socket.getInputStream()的處理)
程式碼如下:
Tcp_client
package SocketCollection;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Tcp_client {
public static void main(String[] args) throws UnknownHostException, IOException {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入要上傳的檔名:");
while (true) {
String line = sc.nextLine();
File file = new File(line);
// 1、驗證是否存在並且為資料夾
if (!file.exists()) {
System.out.println("路徑不存在");
} else if (file.isDirectory()) {
System.out.println("是資料夾路徑,請輸入檔案路徑");
} else {
// 2、傳送檔名到客戶端
Socket socket = new Socket("127.0.0.1", 12345);
BufferedReader bre = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(file.getName());// 是檔名,不是tostring,這是將檔案路徑變成字串
// 3、接受結果,如果存在給與提示,程式直接退出,如果不存在,上傳
String result = bre.readLine();
if (result.equals("檔案存在")) {
System.out.println("您上傳的檔案已經存在,請不要重複上傳!");
socket.close();
return; // 特別注意:返回值為void的方法,從某個判斷中跳出,必須用return;
} else if (result.equals("檔案不存在")) { // 這個地方可以直接不用寫,為了好看就寫上了
FileInputStream fin = new FileInputStream(file);
byte[] arr = new byte[1024 * 8];
int len;
while ((len = fin.read(arr)) != -1) {
ps.write(arr, 0, len);
}
fin.close();
socket.close();
}
}
}
// System.out.println(bre.readLine());
}
}
Tcp_server
package SocketCollection;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import cn.njupt.file;
public class Tcp_server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(12345);
while (true) {
final Socket socket = server.accept();
new Thread() {
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader bre = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = bre.readLine();
File dir = new File("update"); // 建立資料夾存放這個檔案,我覺得是可選的
dir.mkdir();
File file = new File(dir, line);
if (file.exists()) {
ps.println("檔案存在");
socket.close(); // 關閉
return;
} else {
ps.println("檔案不存在");
}
FileOutputStream fout = new FileOutputStream(file);
byte[] arr = new byte[1024 * 8];
int len;
while ((len = is.read(arr)) != -1) {
fout.write(arr, 0, len);
}
fout.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
}