天天看點

網絡程式設計之Socket通信(Java)

       最近在學習Java網絡程式設計,之前聽說過,但是一直都沒有認真了解過。這幾天突然來了興緻,覺得很神奇,忽然就想要了解下具體是什麼個情況。

        Socket通常也稱作"套接字",用于描述IP位址和端口,是一個通信鍊的句柄。在Internet上的主機一般運作了多個服務軟體,同時提供幾種服務。每種服務都打開一個Socket,并綁定到一個端口上,不同的端口對應于不同的服務。

       Socket非常類似于電話插座。以一個國家級電話網為例,電話的通話雙方相當于互相通信的2個程序,區号是它的網絡位址;區内一個機關的交換機相當于一台主機,主機配置設定給每個使用者的局内号碼相當于Socket号。任何使用者在通話之前,首先要占有一部電話機,相當于申請一個Socket;同時要知道對方的号碼,相當于對方有一個固定的Socket。然後向對方撥号呼叫,相當于發出連接配接請求(假如對方不在同一區内,還要撥對方區号,相當于給出網絡位址)。假如對方在場并空閑(相當于通信的另一主機開機且可以接受連接配接請求),拿起電話話筒,雙方就可以正式通話,相當于連接配接成功。雙方通話的過程,是一方向電話機發出信号和對方從電話機接收信号的過程,相當于向Socket發送資料和從socket接收資料。通話結束後,一方挂起電話機相當于關閉Socket,撤消連接配接。

        在電話系統中,一般使用者隻能感受到本地電話機和對方電話号碼的存在,建立通話的過程,話音傳輸的過程以及整個電話系統的技術細節對他都是透明的,這也與Socket機制非常相似。Socket利用網間網通信設施實作程序通信,但它對通信設施的細節毫不關心,隻要通信設施能提供足夠的通信能力,它就滿足了。

以上這些都是百度百科裡面的定義與解釋,不過看着也還是蠻容易了解的,不像之前有的解釋很不容易了解,專業術語太多,了解起來特别費勁。

Socket通信實作步驟:

        1、建立ServerSocket和Socket

        2、打開連接配接Socket的輸入/輸出流

        3、按照協定(通常是TCP/UDP)對Socket進行讀寫操作

        4、關閉輸入/輸出流,關閉Socket

Socket通信模型如下圖所示:

網絡程式設計之Socket通信(Java)

1、Server伺服器端:

a、建立ServerSocket對象,同時綁定監聽端口

b、通過accept()方法監聽用戶端的請求

c、建立連接配接後,通過輸入流讀取用戶端發送的請求資訊

d、通過輸出流向用戶端發送響應資訊

e、關閉相應資源

[java] view plain copy print ?

  1. package com.test;  
  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. import java.util.Date;  
  11. public class ServerSocketDemo {  
  12.     public static void main(String[] args) {  
  13.         try {  
  14.             //1、建立一個服務端Socket,即ServerSocket對象,指定綁定的端口,并偵聽該端口  
  15.             ServerSocket serverSocket = new ServerSocket(5555);  
  16.             //2、調用accept()方法開始偵聽用戶端請求,建立Socket,等待用戶端的連接配接  
  17.             System.out.println("===================伺服器即将啟動,等待用戶端的連接配接===============");  
  18.             Socket socket = serverSocket.accept();  
  19.             //3、擷取輸入位元組流,讀取用戶端請求資訊  
  20.             InputStream is = socket.getInputStream();  
  21.             //将位元組流包裝成字元流  
  22.             InputStreamReader isr = new InputStreamReader(is);  
  23.             //為字元輸入流添加緩沖  
  24.             BufferedReader br = new BufferedReader(isr);  
  25.             //讀取字元輸入流中的資料資訊  
  26.             String data = null;  
  27.             while(null != (data = br.readLine())){  
  28.                 System.out.println(new Date());  
  29.                 System.out.println("我是伺服器端,用戶端說:"+data);  
  30.             }  
  31.             //調用shutdown方法關閉輸入流  
  32.             socket.shutdownInput();  
  33.             //4、擷取輸出位元組流,響應用戶端的資訊  
  34.             OutputStream os = socket.getOutputStream();  
  35.             //将位元組流包裝成為字元列印流  
  36.             PrintWriter pw = new PrintWriter(os);  
  37.             //向用戶端回複響應消息  
  38.             pw.write("使用者名和密碼輸入正确");  
  39.             //重新整理緩存  
  40.             pw.flush();  
  41.             //關閉socket輸出流  
  42.             socket.shutdownOutput();  
  43.             //5、關閉資源  
  44.             pw.close();  
  45.             os.close();  
  46.             br.close();  
  47.             isr.close();  
  48.             is.close();  
  49.             socket.close();  
  50.             serverSocket.close();  
  51.         } catch (IOException e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.     }  
  55. }  
package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * 基于TCP協定的服務端Socket通信
 * 伺服器端必須早于用戶端啟動
 * @author feizi
 *
 */
public class ServerSocketDemo {

	public static void main(String[] args) {
		try {
			//1、建立一個服務端Socket,即ServerSocket對象,指定綁定的端口,并偵聽該端口
			ServerSocket serverSocket = new ServerSocket(5555);
			
			//2、調用accept()方法開始偵聽用戶端請求,建立Socket,等待用戶端的連接配接
			System.out.println("===================伺服器即将啟動,等待用戶端的連接配接===============");
			Socket socket = serverSocket.accept();
			
			//3、擷取輸入位元組流,讀取用戶端請求資訊
			InputStream is = socket.getInputStream();
			
			//将位元組流包裝成字元流
			InputStreamReader isr = new InputStreamReader(is);
			
			//為字元輸入流添加緩沖
			BufferedReader br = new BufferedReader(isr);
			
			//讀取字元輸入流中的資料資訊
			String data = null;
			while(null != (data = br.readLine())){
				System.out.println(new Date());
				System.out.println("我是伺服器端,用戶端說:"+data);
			}
			//調用shutdown方法關閉輸入流
			socket.shutdownInput();
			
			//4、擷取輸出位元組流,響應用戶端的資訊
			OutputStream os = socket.getOutputStream();
			
			//将位元組流包裝成為字元列印流
			PrintWriter pw = new PrintWriter(os);
			
			//向用戶端回複響應消息
			pw.write("使用者名和密碼輸入正确");
			//重新整理緩存
			pw.flush();
			
			//關閉socket輸出流
			socket.shutdownOutput();
			
			//5、關閉資源
			pw.close();
			os.close();
			br.close();
			isr.close();
			is.close();
			socket.close();
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
           

2、Client用戶端:

a、建立Socket對象,指明需要連接配接的伺服器的位址和端口号

b、建立連接配接後,通過輸出流向伺服器端發送請求資訊

c、通過輸入流擷取伺服器的響應資訊

d、關閉相應資源

[java] view plain copy print ?

  1. package com.test;  
  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. import java.util.Date;  
  11. public class ClientSocketDemo {  
  12.     public static void main(String[] args) {  
  13.         try {  
  14.             //1、建立用戶端Socket,指定伺服器位址和端口号,向服務端發送請求資訊  
  15.             Socket socket = new Socket("localhost", 5555);  
  16.             //2、擷取輸出位元組流,向伺服器端發送消息  
  17.             OutputStream os = socket.getOutputStream();  
  18.             //3、将位元組輸出流包裝為字元列印流  
  19.             PrintWriter pw = new PrintWriter(os);  
  20.             //向伺服器端發送請求資訊  
  21.             StringBuffer bf = new StringBuffer();  
  22.             bf.append("使用者名:").append("admin");  
  23.             bf.append("密碼:").append("123");  
  24.             pw.write(bf.toString());  
  25.             //重新整理緩存  
  26.             pw.flush();  
  27.             //關閉Socket的輸出流  
  28.             socket.shutdownOutput();  
  29.             //3、擷取輸入位元組流,讀取伺服器端的響應資訊  
  30.             InputStream is = socket.getInputStream();  
  31.             //将輸入位元組流包裝成字元字元流  
  32.             InputStreamReader isr = new InputStreamReader(is);  
  33.             //為字元流添加緩沖區  
  34.             BufferedReader br = new BufferedReader(isr);  
  35.             //通過伺服器端的響應資訊  
  36.             String data = null;  
  37.             while(null != (data=br.readLine())){  
  38.                 System.out.println(new Date());  
  39.                 System.out.println("我是用戶端,伺服器端說:"+data);  
  40.             }  
  41.             //關閉Socket輸入流  
  42.             socket.shutdownInput();  
  43.             //4、關閉資源  
  44.             br.close();  
  45.             isr.close();  
  46.             is.close();  
  47.             pw.close();  
  48.             os.close();  
  49.             socket.close();  
  50.         } catch (UnknownHostException e) {  
  51.             e.printStackTrace();  
  52.         } catch (IOException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.     }  
  56. }  
package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

/**
 * 基于TCP協定的用戶端Socket通信
 * @author feizi
 *
 */
public class ClientSocketDemo {

	public static void main(String[] args) {
		try {
			//1、建立用戶端Socket,指定伺服器位址和端口号,向服務端發送請求資訊
			Socket socket = new Socket("localhost", 5555);
			
			//2、擷取輸出位元組流,向伺服器端發送消息
			OutputStream os = socket.getOutputStream();
			
			//3、将位元組輸出流包裝為字元列印流
			PrintWriter pw = new PrintWriter(os);
			
			//向伺服器端發送請求資訊
			StringBuffer bf = new StringBuffer();
			bf.append("使用者名:").append("admin");
			bf.append("密碼:").append("123");
			pw.write(bf.toString());
			
			//重新整理緩存
			pw.flush();
			//關閉Socket的輸出流
			socket.shutdownOutput();
			
			//3、擷取輸入位元組流,讀取伺服器端的響應資訊
			InputStream is = socket.getInputStream();
			
			//将輸入位元組流包裝成字元字元流
			InputStreamReader isr = new InputStreamReader(is);
			
			//為字元流添加緩沖區
			BufferedReader br = new BufferedReader(isr);
			
			//通過伺服器端的響應資訊
			String data = null;
			while(null != (data=br.readLine())){
				System.out.println(new Date());
				System.out.println("我是用戶端,伺服器端說:"+data);
			}
			//關閉Socket輸入流
			socket.shutdownInput();
			
			//4、關閉資源
			br.close();
			isr.close();
			is.close();
			pw.close();
			os.close();
			socket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
           

這篇隻介紹到了單個用戶端與伺服器端之間的通信,下一篇會介紹到利用線程實作多個用戶端與伺服器進行通信。

Java網絡程式設計之Socket通信(二)

好了,今天就到這兒了,每天學習一點點,不斷成長,不斷進步,不久你就會改變!