在上一篇博文中,簡單介紹了Socket的簡單通信,這篇博文中將針對它進行簡單的運用。接下來的例子是參考《Android應用開發揭祕》,不過上面有些小問題,例如字符編碼問題。下面直接看下實現過程。
1、服務器:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static int PORT = 54327;
private static List<Socket> mSocketList = new ArrayList<Socket>();
private ExecutorService mExcutorService;
private ServerSocket mServerSocket;
public static void main(String[] args) {
new Server();
}
public Server() {
try {
mServerSocket = new ServerSocket(PORT);
mExcutorService = Executors.newCachedThreadPool();
Socket client = null;
while (true) {
client = mServerSocket.accept();
mSocketList.add(client);
mExcutorService.execute(new ThreadServer(client));
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
static class ThreadServer implements Runnable {
private Socket mSocket;
private BufferedReader mBufferedReader;
private PrintWriter mPrintWriter;
private String MSG = "";
public ThreadServer(Socket socket) throws IOException {
this.mSocket = socket;
mBufferedReader = new BufferedReader(new InputStreamReader(
mSocket.getInputStream(),"UTF-8"));
mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true);
MSG = mBufferedReader.readLine();
System.out.println(MSG);
sendMessage();
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while ((MSG = mBufferedReader.readLine()) != null) {
if(MSG.trim().equals("莫:exit")){
MSG="下線了ing...";
System.out.println("read-->" + MSG);
sendMessage();
mSocketList.remove(mSocket);
mBufferedReader.close();
mPrintWriter.close();
mSocket.close();
break;
}
System.out.println("read-->" + MSG);
sendMessage();
}
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
private void sendMessage() throws IOException {
for (Socket client : mSocketList) {
mPrintWriter = new PrintWriter(client.getOutputStream(), true);
mPrintWriter.println(MSG);
}
}
}
}
2、客戶端:
package com.ideal.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class Net_SocketClientActivity extends Activity {
private EditText mUser = null;//輸入
private Button mLogin = null;
private EditText mSendMsg = null;//輸入
private Button mSend = null;
private TextView mTextView = null;//記錄
private Socket mSocket;
private Thread mThread;
private BufferedReader mBufferedReader;
private PrintWriter mPrintWriter;
private String name = "";
private String MSG="";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mUser = (EditText) findViewById(R.id.user);
mLogin = (Button) findViewById(R.id.login);
mSendMsg = (EditText)findViewById(R.id.sendMsg);
mSend = (Button)findViewById(R.id.sentBtn);
mTextView = (TextView)findViewById(R.id.allMassage);
mLogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mLogin.setVisibility(View.GONE);
mUser.setVisibility(View.GONE);
mSocket = new Socket("172.31.100.50",54327);
//轉碼
mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream(),"GBK"));
mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true);
name = mUser.getText().toString();
try {
mPrintWriter.println(name+":login...");
mPrintWriter.flush();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
} catch (Exception e) {
// TODO: handle exception
}
}
});
mSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
String sendMsg = mSendMsg.getText().toString();
mPrintWriter.println(name+":"+sendMsg);
mPrintWriter.flush();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
});
mThread = new Thread(mRunnable);
mThread.start();
}
private Runnable mRunnable =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
MSG=mBufferedReader.readLine();
if(MSG!=null){
mHandler.sendMessage(mHandler.obtainMessage());
}else {
break;
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
};
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
try {
mTextView.append("\n"+MSG);
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/user"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登錄"/>
<EditText
android:id="@+id/sendMsg"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/sentBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="發送" />
<TextView
android:id="@+id/allMassage"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
看下效果圖:
登陸...
登陸成功,等待發送信息...
發送信息
注:上面只是使用了模擬器作爲客戶端和PC作爲服務端通信,當然,可以在多打開幾個模擬器,這相當幾個客戶同時在聊天。如果你是在同一個實驗室裏面進行通行,那麼在另一臺電腦上使用的模擬器同樣也能和其他臺電腦上的模擬器通信。
存在問題:
1、剛開始時在模擬器和PC上都不能正常顯示字符串,後來得知得轉碼。從上面的代碼可看出:
在服務端:
mBufferedReader = new BufferedReader(new InputStreamReader(
mSocket.getInputStream(),"UTF-8"));
在客戶端:
mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream(),"GBK"));
2、模擬器上完全實現和PC正常通信,但是如果使用真機作爲客戶端,則通信不了。目前知道原因是,通過SOCKET通信要在同一網段才能實現的。由於條件問題,所以這個改天再調試看看。