1. 程式人生 > >客戶端與伺服器的資料傳輸

客戶端與伺服器的資料傳輸

Java最初是作為網路程式語言出現的,它對網路的高度支援,使得客戶端和伺服器流暢的溝通變成現實。而在網路程式設計中,使用最多的就是Socket,每一個實用的網路程式都少不了它的參與。但Socket的底層機制卻相當棘手,幸運的是,Java平臺給我們一些雖然簡單但是相當強大的類,可以使你更簡單有效的使用Socket開發而無需瞭解底層機制。

請思考一下網路程式設計要解決的問題:而下面這些問題都可以用Socket來解決

  1. 如何建立兩個節點(電腦)之間的網路連線?
  2. 如何向另外一個節點(電腦)傳送資訊?
  3. 如何從外部節點(電腦)接收一個請求並給予響應?
  4. 如何利用網路協議(TCP、UPD)?
Socket在英文中是插座的意思,在應用程式中稱為“套接字”,應用程式通過“套接字”向網路發現請求或者應答網路請求,最早是UNIX上的一套網路程式通訊的標準,

已被廣泛移植到了其他平臺。

Socket實質上提供了程序通訊的端點,網路上的兩個程式通過一個雙向的通訊鏈路實現資料的交換,這個雙向鏈路的一端稱為一個Socket。


ServerSocket類常用方法如下:



O了,講了這麼多理論原理的東西,我來講講編碼方面的知識吧,上述理論只是過一個大概,並不詳細,若對理論感興趣的,可以上網上查詢相關資料:

 我寫了一個簡單的例子:一個Socket伺服器,一個是呼叫此伺服器埠的客戶端。以下例子就是客戶端向伺服器的請求。程式碼如下:

  1. package com.qhs.sockettest;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. /**
  9. * Socket伺服器相關程式碼
  10. * 編碼完成後,要先執行伺服器開啟埠,然後再執行客戶端。
  11. */
  12. public class LoginServer {
  13. public static void main(String args []){
  14. try {
  15. //1.建立一個伺服器Socket繫結一個埠並開始監聽
  16. ServerSocket serverSocket = new ServerSocket(8800
    );
  17. //2.使用accept()方法阻塞等待監聽,獲得新的連線
  18. Socket socket = serverSocket.accept();
  19. //3.獲得輸入流
  20. InputStream is = socket.getInputStream();
  21. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  22. //4.獲得使用者輸入資訊
  23. String info = null;
  24. while(!((info=br.readLine())==null)){
  25. System.out.println("我是伺服器,使用者資訊為:" + info);
  26. }
  27. //5.關閉資源
  28. br.close();
  29. is.close();
  30. socket.close();
  31. serverSocket.close();
  32. } catch (IOException e) {
  33. // TODO Auto-generated catch block
  34. e.printStackTrace();
  35. }
  36. }
  37. }
客戶端程式碼如下:
  1. package com.qhs.sockettest;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4. import java.io.PrintWriter;
  5. import java.net.Socket;
  6. import java.net.UnknownHostException;
  7. /**
  8. * 客戶端
  9. */
  10. public class LoginClient {
  11. public static void main(String args []){
  12. try {
  13. //1.建立客服端Socket連線,指定伺服器的位置以及埠
  14. Socket socket = new Socket("localhost", 8800);
  15. //2.得到Socket讀寫流
  16. OutputStream os = socket.getOutputStream();
  17. PrintWriter pw = new PrintWriter(os);
  18. //3.利用流按照一定協議對Socket進行讀/寫操作
  19. String info = "使用者名稱:Jeff;使用者密碼:123456";
  20. pw.write(info);
  21. pw.flush();
  22. //4.關閉資源
  23. pw.close();
  24. os.close();
  25. socket.close();
  26. } catch (UnknownHostException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. } catch (IOException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. }
  33. }
  34. }

測試進行時,請先執行伺服器的程式碼,使得埠開啟。然後再執行客戶端去連線。最後在控制檯輸入的結果如圖:


上面的例子就比如一個人打電話,另外一個人只是聽,不說話,單向通訊。所以執行後,後臺只有客戶端有伺服器的資訊

接下來,我們在上述程式碼中新增一些程式碼,使得伺服器也有響應,等於雙方相互通訊的目的:

伺服器程式碼:

  1. package com.qhs.sockettest;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.io.PrintWriter;
  8. import java.net.ServerSocket;
  9. import java.net.Socket;
  10. /**
  11. * Socket伺服器相關程式碼
  12. * 編碼完成後,要先執行伺服器開啟埠,然後再執行客戶端。
  13. */
  14. public class LoginServer {
  15. public static void main(String args []){
  16. try {
  17. //1.建立一個伺服器Socket繫結一個埠並開始監聽
  18. ServerSocket serverSocket = new ServerSocket(8800);
  19. //2.使用accept()方法阻塞等待監聽,獲得新的連線
  20. Socket socket = serverSocket.accept();
  21. //3.獲得輸入流
  22. InputStream is = socket.getInputStream();
  23. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  24. //伺服器的響應加進來的程式碼:獲得輸出流
  25. OutputStream os = socket.getOutputStream();
  26. PrintWriter pw = new PrintWriter(os);
  27. //4.獲得使用者輸入資訊
  28. String info = null;
  29. while(!((info=br.readLine())==null)){
  30. System.out.println("我是伺服器,使用者資訊為:" + info);
  31. }
  32. //新增程式碼:給客戶一個響應
  33. String reply = "服務的響應>>>>Welcome!";
  34. pw.write(reply);
  35. pw.flush();
  36. //5.關閉資源
  37. pw.close();
  38. os.close();
  39. br.close();
  40. is.close();
  41. socket.close();
  42. serverSocket.close();
  43. } catch (IOException e) {
  44. // TODO Auto-generated catch block
  45. e.printStackTrace();
  46. }
  47. }
  48. }

客戶端程式碼:
  1. package com.qhs.sockettest;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.io.PrintWriter;
  8. import java.net.Socket;
  9. import java.net.UnknownHostException;
  10. /**
  11. * 客戶端
  12. */
  13. public class LoginClient {
  14. public static void main(String args []){
  15. try {
  16. //1.建立客服端Socket連線,指定伺服器的位置以及埠
  17. Socket socket = new Socket("localhost", 8800);
  18. //2.得到Socket讀寫流
  19. OutputStream os = socket.getOutputStream();
  20. PrintWriter pw = new PrintWriter(os);
  21. //新增程式碼:輸入流
  22. InputStream is = socket.getInputStream();
  23. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  24. //3.利用流按照一定協議對Socket進行讀/寫操作
  25. String info = "使用者名稱:Jeff;使用者密碼:123456";
  26. pw.write(info);
  27. pw.flush();
  28. socket.shutdownOutput(); //關閉socket
  29. //新增程式碼:接收伺服器響應並列印顯示
  30. String reply = null;
  31. while(!((reply=br.readLine())==null)){
  32. System.out.println("我是客戶端,接收到伺服器的響應為:" + reply);
  33. }
  34. //4.關閉資源
  35. br.close();
  36. is.close();
  37. pw.close();
  38. os.close();
  39. socket.close();
  40. } catch (UnknownHostException e) {
  41. // TODO Auto-generated catch block
  42. e.printStackTrace();
  43. } catch (IOException e) {
  44. // TODO Auto-generated catch block
  45. e.printStackTrace();
  46. }
  47. }
  48. }

我們執行測試一下,先執行伺服器,再執行客戶端。我們會看到,這次後臺不只是客戶端接收到了伺服器給的請求資訊,在伺服器後臺,也輸出了相應的響應資訊:我們可以點選下圖所示的切換來檢視客戶端與伺服器接收與響應的後臺資訊:

最後,我們來總結一下Socket中伺服器與客戶端的各步驟。

伺服器端:

  1. 建立一個伺服器Socket繫結指定的埠並開始監聽;
  2. 使用accept()方法阻塞等待監聽,獲取新的連線;
  3. 建立輸入和輸出流;
  4. 在已有的協議上產生會話;
  5. 使用close()方法關閉流和Socket;
客戶端:
  1. 建立客戶端Socket連線,指定伺服器的位置以及埠;
  2. 得到Socket的讀寫流;
  3. 利用流按照一定的協議對Socket進行讀/寫操作;
  4. 使得close()方法關閉流和Socket

這是Socket網路程式設計之傳遞字元型別,接下來我會在我部落格另外一篇中Socket升級傳遞物件程式設計