1.Socket简单介绍
- Socket可以实现进程间通信,Socket称为”套接字”,它分为流式套接字和用户数据套接字, 分别对应网络中的TCP和UDP协议。
- TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立是通过三次握手才能完成,稳定性高,效率相对UDP较低。
- UDP协议是面向无连接的,提供单向通信功能,效率高,不保证数据一定能够正确传输。
- Android4.0以后不能在主线程中请求网络,会抛出异常NetworkOnMainThreadException。
2.客户端的实现
用Socket来进行进程间通信需要加上权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
MainActivity位于默认进程中
public class MainActivity extends Activity
{
private static final int MESSAGE_RECEIVE_NEW_MSG = 1;
private static final int MESSAGE_SOCKET_CONNECTED = 2;
@InjectView(R.id.msg_container)
TextView mMsgContainer;
@InjectView(R.id.msg)
EditText mMsg;
@InjectView(R.id.send)
Button mSend;
private PrintWriter mPrintWriter;
private Socket mClientSocket;
private Handler mHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case MESSAGE_RECEIVE_NEW_MSG:
{
mMsgContainer.setText(mMsgContainer.getText() + (String) msg.obj);
break;
}
case MESSAGE_SOCKET_CONNECTED: {
mSend.setEnabled(true);
break;
}
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
clickEent();
Intent service = new Intent(this, TcpService.class);
startService(service);
new Thread()
{
@Override
public void run()
{
connectTCPServer();
}
}.start();
}
private void clickEent()
{
mSend.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
if (view== mSend)
{
final String msg = mMsg.getText().toString();
if (!TextUtils.isEmpty(msg) && mPrintWriter != null)
{
mPrintWriter.println(msg);
mMsg.setText("");
String time = formatDateTime(System.currentTimeMillis());
final String showedMsg = "客户端" + time + ":" + msg + "\n";
mMsgContainer.setText(mMsgContainer.getText() + showedMsg);
}
}
}
});
}
@Override
protected void onDestroy() {
if (mClientSocket != null) {
try {
mClientSocket.shutdownInput();
mClientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
super.onDestroy();
}
private String formatDateTime(long time)
{
return new SimpleDateFormat("(HH:mm:ss)").format(new Date(time));
}
private void connectTCPServer()
{
Socket socket = null;
while (socket == null)
{
try
{
socket = new Socket("localhost", 8088);
mClientSocket = socket;
mPrintWriter = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true);
mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);
}
catch (IOException e)
{
SystemClock.sleep(1000);
}
}
try
{
// 接收服务器端的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (!MainActivity.this.isFinishing())
{
String msg = br.readLine();
if (msg != null) {
String time = formatDateTime(System.currentTimeMillis());
final String showedMsg = "服务端" + time + ":" + msg + "\n";
mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showedMsg).sendToTarget();
}
}
Utils.close(mPrintWriter);
Utils.close(br);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.服务端的实现
TcpService位于私有进程中
<service
android:name=".service.TcpService"
android:process=":remote"/>
public class TcpService extends Service
{
private boolean mIsServiceDestoryed = false;
private String[] mDefinedMessages = new String[] {
"你好?",
"请问你叫什么名字呀?",
"吃饭了吗",
"今天可以一起去看电影啊",
"你的快递收到了吗",
"今天北京的天气不错啊",
"明天周末准备到哪玩啊?"
};
@Override
public void onCreate() {
new Thread(new TcpServer()).start();
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
mIsServiceDestoryed = true;
super.onDestroy();
}
private class TcpServer implements Runnable {
@SuppressWarnings("resource")
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8088);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (!mIsServiceDestoryed) {
try {
// 接受客户端请求
final Socket client = serverSocket.accept();
new Thread() {
@Override
public void run() {
try {
responseClient(client);
} catch (IOException e) {
e.printStackTrace();
}
};
}.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void responseClient(Socket client) throws IOException {
// 用于接收客户端消息
BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
// 用于向客户端发送消息
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client.getOutputStream())), true);
out.println("欢迎来到聊天室!");
while (!mIsServiceDestoryed) {
String str = in.readLine();
if (str == null) {
break;
}
int i = new Random().nextInt(mDefinedMessages.length);
String msg = mDefinedMessages[i];
out.println(msg);
}
// 关闭流
Utils.close(out);
Utils.close(in);
client.close();
}
}
4.下载地址和运行结果截图
运行结果截图: