Socket通訊簡單點理解就是通訊雙方通過某個端口進行數據的相互傳輸,與常用的http的請求-響應方式不同,Socket通訊無需客戶端向服務器發送請求,然後服務器在響應,直接就是進行數據傳輸。
一、Socket的類型
Socket有兩種類型:
1、基於TCP協議傳輸數據的streamsocket;
2、基於UDP協議傳輸數據的datagramsocket。
傳輸過程如下:
通常我們都使用TCP協議傳輸
如上圖Socket也分爲服務器端和客戶端,實際上一臺機器既可以是服務端也可以是客戶端,而兩端 之間通過字節流傳輸數據
二、Socket的具體實現
這裏的實現基於TCP協議的方式
1、首先在服務端先創建一個工作線程類來處理數據
public class MessageRunnable implements Runnable{
private Socket socket=null;
public MessageRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
//獲取輸入輸出流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
//把數據寫回客戶端
// String toClientStr="稍等下..客服忙...";
// os.write(toClientStr.getBytes("utf-8"));
// os.flush();
//停止socket輸出(半關閉狀態)
// socket.shutdownOutput();
//讀取客戶端數據
BufferedReader bf=new BufferedReader(new InputStreamReader(is));
String line=null;
String dataFromClient="";
while ((line=bf.readLine())!=null) {
dataFromClient+=line;
}
System.out.println("來自客戶端:"+dataFromClient);
socket.shutdownInput();
os.write(dataFromClient.getBytes("utf-8"));
os.flush();
os.close();
is.close();
socket.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
主要是獲取輸入輸出流的方法,輸入流就是外界接收過來的數據流,輸出流就是本地向外界發送的數據流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
2、然後再主線程創建ServerSocket對象
ServerSocket service=new ServerSocket(SOCKET_PORT);
上面方法傳遞的參數是通訊的端口號
3、通過ServerSocket對象的accept的方法獲取來自客戶端的socket對象
如果有數據過來就往下執行,否則就處於堵塞狀態
while(true){
//監聽客戶送發過來的信息
Socket socket=service.accept();
new Thread(new MessageRunnable(socket)).start();
}
4、在客戶端創建好Socket對象,因爲是網絡操作所以要授權和在子線程運行,所以這裏通過handle的消息機制來更新UI
//構造用於發送socket線程
private class SocketThread extends Thread{
String message;
SocketThread(String messsage){
this.message=messsage;
}
@Override
public void run() {
try {
socket=new Socket();
socket.connect(new InetSocketAddress("192.168.1.100",8888),5000);
//獲取輸入輸出流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
BufferedReader bf=new BufferedReader(new InputStreamReader(is));
os.write(message.getBytes("utf-8"));
os.flush();
String line=null;
String buff="";
while ((line=bf.readLine())!=null){
buff+=line+"\n";
}
//發消息用於展示界面
Message msg=Message.obtain();
msg.what=MESSAGE_FLAG;
Bundle bundle=new Bundle();
bundle.putString("text",buff);
msg.setData(bundle);
handler.sendMessage(msg);
os.close();
is.close();
bf.close();
socket.close();
}catch (SocketTimeoutException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//處理子線程消息
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==MESSAGE_FLAG){
Bundle bundle=msg.getData();
String message=bundle.getString("text");
tvDisplay.append("Server說:"+message+"\n");
}
super.handleMessage(msg);
}
};
客戶端這邊通過connect方法連接到服務端的端口實現雙方的通訊
三、總結
Socket是對TCP(UDP)協議的應用,主要應用場景是實時通信、遊戲之類的要求網絡能快速回應而不像http協議那般要發送請求才會獲取響應,socket發生的網絡連接,端與端之間可以主動推送數據,使數據響應更爲及時,當然這樣長時間的實時響應是很耗電的,所以一般長時間沒有數據傳遞都會關閉連接。