在上一篇博文中,简单介绍了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通信要在同一网段才能实现的。由于条件问题,所以这个改天再调试看看。