您好,登錄后才能下訂單哦!
Java中能接受其他通信實體鏈接請求的類是ServerSocket,ServerSocket對象用于監聽來自客戶端的Socket鏈接,如果沒有鏈接,它將一直等待。如果接收到一個客戶端Socket的連接請求,ServerSocket的accept()方法將返回一個與客戶端Socket對應的Socket(每個TCP連接有兩個Socket),否則該方法將一直阻塞,線程也被阻塞。
服務端思路:服務端應該包含多個線程,每個Socket對應一個線程,這個線程負責讀取該Socket對應輸入流的數據(從客戶端發送過來的數據),并將讀到的數據向每個Socket輸出流發送一次(將一個客戶端發送過來的數據“廣播”給其他客戶端)。
服務端代碼:
//服務端主類 public class MyServer { public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<Socket>()); public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(30000); while (true) { //此行代碼會阻塞,將一直等待別人的連接 Socket s = ss.accept(); socketList.add(s); //每當客戶端連接后啟動一個ServerThread線程為該客戶端服務 new Thread(new ServerThread(s)).start(); } } }
public class ServerThread implements Runnable { //定義當前線程所處理的Socket Socket s = null; //該線程所處理的Socket對應的輸入流 BufferedReader br = null; public ServerThread(Socket s) throws IOException { this.s = s; //初始化該Socket對應的輸入流 br = new BufferedReader(new InputStreamReader(s.getInputStream())); } @Override public void run() { try { String content = null; //采用循環不斷地從Socket中讀取客戶端發送來的數據 while ((content = readFromClient()) != null) { //遍歷socketList中的每個Socket //將讀到的內容向每個Socket發送一次 for (Socket s : MyServer.socketList) { PrintStream ps = new PrintStream(s.getOutputStream()); ps.println(content); } } } catch (IOException e) { e.printStackTrace(); } } //定義讀取客戶端數據的方法 private String readFromClient() { try { return br.readLine(); } //如果捕獲到異常,則表明該Socket對應的客戶端已經關閉 catch (IOException e) { //刪除該Socket MyServer.socketList.remove(s); } return null; } }
客戶端思路:將用戶輸入的數據寫入Socket對應的輸入流中;開啟一個子線程讀取Socket對應輸入流中的數據(從服務端發送過來的數據),并通過Handler將讀取的數據發送到主線程來更新UI。
//用戶界面Activity public class MainActivity extends Activity { private EditText mReceiverMsg; private Button mSendBtn; private EditText mSendMsg; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { Log.d("mainActivity" , "okk"); mReceiverMsg.append(msg.obj.toString()); } }; private Socket s; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); initView(); initSocket(); mSendBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sendData(); } }); } private void initSocket() { new Thread() { @Override public void run() { try { s = new Socket("192.168.1.101" , 30000); new Thread(new ClientThread(s , handler)).start(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } private void initView() { mReceiverMsg = (EditText) findViewById(R.id.receiver_message); mSendMsg = (EditText) findViewById(R.id.send_message); mSendBtn = (Button) findViewById(R.id.send_button); } private void sendData() { try { //獲取該Socket對應的輸出流 PrintStream ps = new PrintStream(s.getOutputStream()); if (TextUtils.isEmpty(mSendMsg.getText())) { Toast.makeText(this , "請輸入信息" , Toast.LENGTH_LONG).show(); return; } ps.println(mSendMsg.getText().toString()); } catch (IOException e) { e.printStackTrace(); } } }
public class ClientThread implements Runnable { //該線程負責處理的Socket private Socket ss; //該線程所處理的Socket對應的輸入流 BufferedReader br = null; Handler handler; public ClientThread(Socket s , Handler handler) throws IOException { this.ss = s; this.handler = handler; br = new BufferedReader(new InputStreamReader(ss.getInputStream())); } @Override public void run() { try { String content = null; while ((content = br.readLine()) != null) { Message msg = new Message(); msg.obj = content; handler.sendMessage(msg); } } catch (IOException e) { e.printStackTrace(); } } }
先運行上面程序中的MyServer類,該類運行只是作為服務端。再啟動多個模擬器,運行安裝客戶端的程序作為多個客戶端,然后可以再任何一個客戶端通過Edit輸入一些內容,點擊發送就可以在任何一個客戶端看到剛剛輸入的內容。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。