1. 程式人生 > >javaSE (四十)網路程式設計(TCP傳輸、伺服器多執行緒、網路程式設計練習:反轉字串、上傳檔案)

javaSE (四十)網路程式設計(TCP傳輸、伺服器多執行緒、網路程式設計練習:反轉字串、上傳檔案)

在這裡插入圖片描述

1、TCP傳輸:

1.客戶端

  1. 建立Socket連結服務端(指定ip地址,埠號),通過ip地址找到對應的伺服器
  2. 呼叫Socket的getInputStream和getOutputStream方法獲取和伺服器端相連的IO流

2.伺服器端

  1. 建立ServerSocket(指定埠號)
  2. 呼叫ServerSocket的accept方法接收一個客戶端請求,得到一個Socket
  3. 呼叫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、伺服器多執行緒:

簡單地將伺服器端改為多執行緒,應對更多的請求

思路:

  1. while迴圈
  2. 匿名內部類,來一個請求就開一個執行緒

修改服務端程式碼如下:

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:客戶端鍵入字串,伺服器端反轉傳回,客戶端接收反轉後的字串

思路:

  1. 反轉嘛,就想到了StringBuilde.reverse()
  2. 然後客戶端傳過來用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());

效果如圖:
在這裡插入圖片描述

練習二:上傳檔案

思路:

  1. 客戶端鍵入字串,驗證是否為檔名
  2. 客戶端傳送檔名到伺服器端
  3. 伺服器建立資料夾存放此檔案(可選),驗證伺服器端是否有此檔案並返回驗證結果
  4. 客戶端接收結果,若存在,程式停止,若不存在,上傳檔案(IO流FileInputStream /FileOutputStream)
  5. 伺服器端接收檔案(傳的是檔案的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();

		}

	}

}