最近在學習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通信模型如下圖所示:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcxGbHpFerR1T4VFShZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO2kDMykjMzETMwETM0EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
1、Server伺服器端:
a、建立ServerSocket對象,同時綁定監聽端口
b、通過accept()方法監聽用戶端的請求
c、建立連接配接後,通過輸入流讀取用戶端發送的請求資訊
d、通過輸出流向用戶端發送響應資訊
e、關閉相應資源
[java] view plain copy print ?
- 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;
- 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();
- }
- }
- }
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 ?
- 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;
- 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();
- }
- }
- }
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通信(二)
好了,今天就到這兒了,每天學習一點點,不斷成長,不斷進步,不久你就會改變!