Android實現(xiàn)C/S聊天室
Java中能接受其他通信實體鏈接請求的類是ServerSocket,ServerSocket對象用于監(jiān)聽來自客戶端的Socket鏈接,如果沒有鏈接,它將一直等待。如果接收到一個客戶端Socket的連接請求,ServerSocket的accept()方法將返回一個與客戶端Socket對應(yīng)的Socket(每個TCP連接有兩個Socket),否則該方法將一直阻塞,線程也被阻塞。
服務(wù)端思路:服務(wù)端應(yīng)該包含多個線程,每個Socket對應(yīng)一個線程,這個線程負責(zé)讀取該Socket對應(yīng)輸入流的數(shù)據(jù)(從客戶端發(fā)送過來的數(shù)據(jù)),并將讀到的數(shù)據(jù)向每個Socket輸出流發(fā)送一次(將一個客戶端發(fā)送過來的數(shù)據(jù)“廣播”給其他客戶端)。
服務(wù)端代碼:
//服務(wù)端主類
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線程為該客戶端服務(wù)
new Thread(new ServerThread(s)).start();
}
}
}
public class ServerThread implements Runnable
{
//定義當前線程所處理的Socket
Socket s = null;
//該線程所處理的Socket對應(yīng)的輸入流
BufferedReader br = null;
public ServerThread(Socket s) throws IOException
{
this.s = s;
//初始化該Socket對應(yīng)的輸入流
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
@Override
public void run()
{
try
{
String content = null;
//采用循環(huán)不斷地從Socket中讀取客戶端發(fā)送來的數(shù)據(jù)
while ((content = readFromClient()) != null)
{
//遍歷socketList中的每個Socket
//將讀到的內(nèi)容向每個Socket發(fā)送一次
for (Socket s : MyServer.socketList)
{
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(content);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
//定義讀取客戶端數(shù)據(jù)的方法
private String readFromClient()
{
try
{
return br.readLine();
}
//如果捕獲到異常,則表明該Socket對應(yīng)的客戶端已經(jīng)關(guān)閉
catch (IOException e)
{
//刪除該Socket
MyServer.socketList.remove(s);
}
return null;
}
}
客戶端思路:將用戶輸入的數(shù)據(jù)寫入Socket對應(yīng)的輸入流中;開啟一個子線程讀取Socket對應(yīng)輸入流中的數(shù)據(jù)(從服務(wù)端發(fā)送過來的數(shù)據(jù)),并通過Handler將讀取的數(shù)據(jù)發(fā)送到主線程來更新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對應(yīng)的輸出流
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
{
//該線程負責(zé)處理的Socket
private Socket ss;
//該線程所處理的Socket對應(yīng)的輸入流
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類,該類運行只是作為服務(wù)端。再啟動多個模擬器,運行安裝客戶端的程序作為多個客戶端,然后可以再任何一個客戶端通過Edit輸入一些內(nèi)容,點擊發(fā)送就可以在任何一個客戶端看到剛剛輸入的內(nèi)容。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用SurfaceView實現(xiàn)下雨與下雪動畫效果詳解(Kotlin語法)
這篇文章主要給大家介紹了關(guān)于利用SurfaceView實現(xiàn)下雨與下雪動畫效果的相關(guān)資料,需要一些基本的View知識和會一些基礎(chǔ)Kotlin語法,文中給出了詳細的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09
Android TextView中文字通過SpannableString設(shè)置屬性用法示例
這篇文章主要介紹了Android TextView中文字通過SpannableString設(shè)置屬性用法,結(jié)合實例形式分析了TextView控件中SpannableString類相關(guān)屬性的使用技巧,需要的朋友可以參考下2016-08-08
Android fragment實現(xiàn)多個頁面切換效果
這篇文章主要為大家詳細介紹了fragment實現(xiàn)多個頁面切換效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04

