1文章來由:突然被問到會不會APP和PC進行通信,當時也是一臉懵逼,然後百度下,發現是用Socekt來進行通信的,沒錯,就是當初我們學java基礎篇的時候做聊天的Socket。
2。下面就直接上demo,一個客戶端和服務器通信的例子,具體安卓和pc通信的過程類似,因爲沒有測試,下次再進行上傳。
a.首先寫客戶端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class TClient{
//服務端ip地址,這裏用本地進行測試
private static final String IP_ADDR = "127.0.0.1";
private static final int PORT = 8099;//使用的端口號
private Socket chart;//建立一個Socket
private BufferedReader burf;//使用緩衝流來讀從服務器返回的數據
private PrintWriter pw;//標準的String類型,向服務端發送數據
public void go() {
//使用while可以讓本次連接一直進行,直到客戶端判斷手動結束線程,不然,本次通信只能進行一次,就會自動關閉。
while(true){
try {
chart = new Socket(IP_ADDR,PORT);//向服務端請求
//從socket中獲取獲取返回的流
burf = new BufferedReader(new InputStreamReader(chart.getInputStream(),"utf-8"));
//向socket寫入輸出流,true表示強行輸出緩存
pw = new PrintWriter(new OutputStreamWriter(chart.getOutputStream(),"utf-8"),true);
//從鍵盤輸入,給服務器發送數據
System.out.println("請輸入: \t");
//讀鍵盤輸入的數據
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line_ = br.readLine();
//發送給服務器
pw.println(line_);
//pw.flush();(如果上面沒有true,這裏必須手動輸出緩存)
//讀取服務器文件
String line = burf.readLine();
System.out.println("服務器返回的數據"+line);
//關閉連接(返回的字符是end的時候,關閉本次連接)
try {
if ("end".equals(line)) {
System.out.println("客戶端將關閉連接");
Thread.sleep(500);//讓這個線程sleep
break; //跳出while循環,連接關閉
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//關閉流
pw.close();
burf.close();
} catch (IOException e) {
System.out.println("無法連接服務器"+e.getMessage());
}finally{
//關閉流和Socket
try {
if(chart != null){
chart.close();
}
} catch (IOException e) {
System.out.println("客戶端異常"+e.getMessage());
}
}
}
}
public static void main(String[] args){
System.out.println("客戶端啓動");
TClient tc = new TClient();
tc.go();
}
}
//客戶端方面,(或者說APP方面),因爲一般一個用戶一個客戶端,所以在客戶端方面使用的是單一線程。
2.下面是重點方,服務器端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class T1Server{
private static final int PORT = 8099;//與客戶端相同的端口
public void go(){
try {
ServerSocket sot = new ServerSocket(PORT);//讓服務器監聽來自改端口的客戶的請求
while(true){
Socket client = sot.accept();//服務器創建一個新的Socket與客服端進行通信
new DealSockets(client);//一個新的線程處理這次通信
}
} catch (IOException e) {
System.out.println("服務器監聽客戶端失敗"+e.getMessage());
}
}
public static void main(String[] args) {
System.out.println("服務端啓動");
T1Server ts = new T1Server();
ts.go();
}
}
//建立一個新的線程處理通信
class DealSockets implements Runnable{
private Socket client;
private BufferedReader bufr;
private PrintWriter bufw;
public DealSockets(Socket client){
this.client = client;
new Thread(this).start();
}
public void run() {
try {
//讀取客戶端返回的數據
bufr = new BufferedReader(new InputStreamReader(client.getInputStream(),"utf-8"));
String line_ = bufr.readLine();
System.out.println("客戶端發送的數據"+line_);
//向客戶端發送數據(這裏寫死了,可以用流從鍵盤輸入,和客戶端的一樣)
bufw = new PrintWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bufw.println("ends");
//在使用bufw後直接調用close();,也可以直接把緩存寫出去
//關閉流
bufw.close();
bufr.close();
} catch (IOException e) {
System.out.println("客戶端輸入流異常:"+e.getMessage());
}finally{
try {
if(client != null){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客戶端處理的時候,(默認的是多個用戶同時要使用服務器),所以加上了while循環,可以讓多個用戶進入,一直監聽客戶端,後面處理通信用了一個新的線程,是爲了讓用戶可以同時和服務端通信,不然的情況就(不使用多線程)是一個用戶使用完本次連接,第二個用戶才能進入。這樣就會出現問題了。
3.這個demo很簡陋,具體實際應用還要看業務需求,比如我這個通訊,寫死了是客戶端發消息,服務器才能返回消息,然後服務器在發送消息。真正在寫聊天的時候,客戶端需要一個新的線程專門從socket中讀取服務器的消息來進行顯示。這樣實用性就會高一點了。
4.如有不當的地方,敬請指正。