第一次接觸Socket是大二時的課程設計,當時做的是圖書管理系統,源碼都是網上下載,考試周拿著代碼天天磨,隱約中記得有Socket這麼一個單詞。
第二次是去年代表學校參加“河北省電子信息職業技能大賽”,接受曹建新師哥的培訓。建新師哥當時用手機Android軟件做客戶端,通過局域網向電腦端服務器傳輸手機錄入的信息。當時我很詫異,客戶端是Android平台,服務器是.Net平台,這兩種平台是如何在局域網內進行通信的呢?建新師哥的回答是:“通過Socket,把數據打包成JSON格式進行傳輸。”從此對Socket的認識便有了一種高大上的感覺。
第三次接觸是通過馬士兵老師的視頻,這次瞬間感覺Socket--So Easy。這也驗證了米老師的那句話:不怕不知道,就怕不知道。
Socket通信分為服務器Socket即ServerSocket和客戶端Socket。
在服務器端,通信前需要建立和客戶端的通信通道,建立對客戶端通信端口號的監聽;在客戶端,通信前需要定義進行通信的主機IP和端口號,創建通信通道。兩者都准備完畢,下面就可以進行通信了。
服務器端代碼:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) {
//創建向客戶端傳輸數據的通道
InputStream in = null;
//創建從客戶端接收數據的通道
OutputStream out = null;
try {
//建立和客戶端的通信,並定義通信端口
ServerSocket ss = new ServerSocket(5888);
//監聽客戶端提交的請求
Socket socket = ss.accept();
in = socket.getInputStream();
out = socket.getOutputStream();
//在字節流的基礎上進行包裝數據流
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
//接收客戶端提交的請求
String s = null;
if ((s = dis.readUTF()) != null) {
System.out.println(s);
System.out.println("from:" + socket.getInetAddress());
System.out.println("port:" + socket.getPort());
}
//向客戶端傳輸數據
dos.writeUTF("hi,hello");
dos.close();
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
由於數據流的readUTF()方法和writeUTF()方法都是阻塞式,所以當A向B發送數據後,如果B沒有響應,A是無法繼續發送數據的,只能傻傻的等待。這個過程好比TCP/IP協議的三次握手,1:A呼叫B,“我是A,收到請回答?”;2:B回應A,“我是B,收到”;3:A繼續說,“我想請你吃飯,你有時間嗎?”。下面A和B就可以進行通信了。
服務器端代碼有了,下面分享客戶端代碼:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) {
//創建向服務器傳輸數據的通道
InputStream in = null;
//創建從服務器接收數據的通道
OutputStream out = null;
try {
//定義進行通信的主機IP和端口號
Socket socket = new Socket("localhost", 5888);
in = socket.getInputStream();
out = socket.getOutputStream();
//在字節流的基礎上進行包裝數據流
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
//向服務器提交數據
dos.writeUTF("hey");
//接收從服務器返回的數據
String s = null;
if ((s = dis.readUTF()) != null) {
System.out.println(s);
}
dos.close();
dis.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
}
通過這個簡單的小Demo,我們就可以清晰的觀察到Socket是如何在服務器端和客戶端進行通信的。
J2SE是JavaWeb和J2EE的基礎,異常處理、IO通道、線程、網絡編程、GUI編程又是J2SE的基礎,所以學好Socket很有必要。
席慕蓉說過一句名言:前世的五百次回眸才能換得今生的一次擦肩而過。所以對於以後的每次擦肩而過都應該認真對待,不要像我,和Socket都擦肩而過好多次了,今天才終於認識它。