Android进程间通信(IPC)之Socket
2016-05-22 16:45
507 查看
Socket也被称为“套接字”编程,它分为流式套接字和用户数据套接字两种,分别对应于网络传输控制中层中TCP和UDP协议。TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立需要经过”三次握手”才能实现,为了实现稳定的数据传输功能,其本身提供了超时重传机制,具有很高的稳定性。UDP是无连接的,提供不稳定的单向通信功能,当然UDP也可以实现双向通信功能,在性能上,UDP就有更好的效率,其缺点是不能保证数据一定传输正确,尤其是网络拥塞的情况下。
演示一个Socket聊天的程序:
服务端
客户端
先看布局代码:
java代码:
客户端和服务端联网需要权限:
演示一个Socket聊天的程序:
服务端
package com.app.service; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import java.util.Random; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class TcpService extends Service { private boolean mIsServiceDestoryed = false; private String[] mDefinedMessage = new String[] { "你好", "hello", "辛苦了" }; private ServerSocket mServerSocket; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); new Thread(new TcpThread()).start(); } class TcpThread implements Runnable { @Override public void run() { try { //服务端在8688这个端口监听 mServerSocket = new ServerSocket(8688); } catch (IOException e) { e.printStackTrace(); return; } while (!mIsServiceDestoryed) { try { //一个阻塞的方法,当有客户端Socket时会运行 final Socket socket = mServerSocket.accept(); new Thread() { @Override public void run() { responseClient(socket); } }.start(); } catch (IOException e) { e.printStackTrace(); } } } } //服务端相应客户端 private void responseClient(Socket socket) { try { //读取客户端发来的消息 BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); //用于向客户端发送消息 PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); out.println("欢迎来到聊天室!"); while (!mIsServiceDestoryed) { String str = in.readLine();//通信连接后,客户端不发消息,这个方法会一直阻塞 Log.e("tag", "客户端消息:====" + str); if (str == null) { break; } int i = new Random().nextInt(mDefinedMessage.length); String msg = mDefinedMessage[i]; out.println(msg);//向客户端发送消息 } //客户端连接断开后,要关闭数据流 in.close(); out.close(); socket.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onDestroy() { mIsServiceDestoryed = true;//停止线程 super.onDestroy(); } }
客户端
先看布局代码:
<?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:background="#fff" android:orientation="vertical" > <EditText android:id="@+id/et_recore" android:layout_width="fill_parent" android:layout_height="200dip" android:gravity="top|left" android:text="聊天记录:\n" > </EditText> <EditText android:id="@+id/et_send_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="输入要发送的内容" > </EditText> <Button android:id="@+id/btn_send" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送" android:textColor="#000" /> </LinearLayout>
java代码:
package com.app.client; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.Socket; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity implements OnClickListener { private static final int MESSAGE_RECEIVE_NEW_MSG = 1; private static final int MESSAGE_SOCKET_CONNECTED = 2; private Button mButton_Send; private EditText mEditText01, mEditText02; private PrintWriter mPintWriter; private Socket mClientSocket; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_RECEIVE_NEW_MSG: mEditText01.setText(mEditText01.getText() + (String) msg.obj); break; case MESSAGE_SOCKET_CONNECTED: mButton_Send.setEnabled(true); mEditText02.setEnabled(true); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton_Send = (Button) findViewById(R.id.btn_send); mEditText01 = (EditText) findViewById(R.id.et_recore); mEditText02 = (EditText) findViewById(R.id.et_send_content); mButton_Send.setEnabled(false); mButton_Send.setOnClickListener(this); //开启服务 Intent i = new Intent("com.app.service"); startService(i); new Thread() { @Override public void run() { connectTCPServer(); } }.start(); } protected void connectTCPServer() { Socket socket = null; //while里面使用了超时重连策略 while (socket == null) { try { socket = new Socket("localhost", 8688); mClientSocket = socket; mPintWriter = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED); } catch (Exception e) { SystemClock.sleep(1000); } } try { //用于读取服务端的消息 BufferedReader br = new BufferedReader(new InputStreamReader( mClientSocket.getInputStream(), "utf-8")); while (!MainActivity.this.isFinishing()) { String msg = br.readLine();//读取 Log.e("tag", "服务端消息:====" + msg); if (msg != null) { String showeMsg = "server : " + msg + "\n"; mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showeMsg) .sendToTarget(); } } //关闭资源 mPintWriter.close(); br.close(); socket.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onClick(View v) { String msg = mEditText02.getText().toString(); if (!TextUtils.isEmpty(msg) && mPintWriter != null) { mPintWriter.println(msg); mEditText02.setText(""); String showMsg = "client : " + msg + "\n"; mEditText01.setText(mEditText01.getText() + showMsg); } } @Override protected void onDestroy() { if (mClientSocket != null) { try { mClientSocket.shutdownInput(); mClientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } super.onDestroy(); } }
客户端和服务端联网需要权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
相关文章推荐
- java-模拟tomcat服务器
- Linux socket 初步
- java socket 注意的地方
- java socket 注意的地方
- C#实现子窗体与父窗体通信方法实例总结
- C#基于socket模拟http请求的方法
- 简单的Ruby中的Socket编程教程
- Socket不能选择本地IP连接问题如何解决
- C#之Socket操作类实例解析
- 使用C#来编写一个异步的Socket服务器
- C#使用Socket快速判断数据库连接是否正常的方法
- java和c#使用hessian通信的方法
- 科学知识:理解socket
- win32下进程间通信(共享内存)实例分析
- Android聊天工具基于socket实现
- php与flash as3 socket通信传送文件实现代码
- 解决time_wait强制关闭socket
- ipc通道入侵相关命令整理
- WinForm实现跨进程通信的方法
- C#中使用UDP通信实例