Android跨进程通信之Socket
2018-01-29 22:27
197 查看
借鉴自开发艺术
Socket,套接字,分为流式套接字TCP,用户数据报套接字UDP。
TCP面向连接,稳定,双向,有着经典的3次挥手、4次挥手,有超时重传机制
UDP面向地址,不稳定,拥塞、复杂网络环境可能会丢失,但效率更高,双向
权限
先在远程Service建立一个TCP服务,再在主界面连接TCP服务,再在服务端进行一定的处理,使得可以接受多个客户端的连接。
这里监听的是8688端口。当有客户端连接的时候,会生成一个新的Socket(如果是真正的服务器,只有一个套接字)
当客户端断开连接时,服务端这边也会关闭对应Socket。这里的实现原理是通过判断服务端输入流的返回值来判断。当客户端断开连接时,服务端的输入流会返回null。
服务端
客户端代码
Socket,套接字,分为流式套接字TCP,用户数据报套接字UDP。
TCP面向连接,稳定,双向,有着经典的3次挥手、4次挥手,有超时重传机制
UDP面向地址,不稳定,拥塞、复杂网络环境可能会丢失,但效率更高,双向
权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
先在远程Service建立一个TCP服务,再在主界面连接TCP服务,再在服务端进行一定的处理,使得可以接受多个客户端的连接。
这里监听的是8688端口。当有客户端连接的时候,会生成一个新的Socket(如果是真正的服务器,只有一个套接字)
当客户端断开连接时,服务端这边也会关闭对应Socket。这里的实现原理是通过判断服务端输入流的返回值来判断。当客户端断开连接时,服务端的输入流会返回null。
服务端
public class TCPServerService extends Service { private static final String TAG = "xbh"; private boolean mIsServiceDestoryed = false; private String[] mDefinedMessages = new String[]{ "hello", "hi", "good", "perfect", "pretty" }; @Override public void onCreate() { new Thread(new TcpServer()).start(); super.onCreate(); } public TCPServerService() { } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { mIsServiceDestoryed = true; super.onDestroy(); } private class TcpServer implements Runnable { @Override public void run() { ServerSocket serverSocket = null;//视为端口 try { serverSocket = new ServerSocket(8688); } catch (IOException e) { Log.e(TAG, "finished, 8688"); e.printStackTrace(); return; } while (!mIsServiceDestoryed) { //正式进入提供服务状态 try { //接受到连接 final Socket client = serverSocket.accept(); Log.i(TAG, "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); Log.i(TAG, "Welcome"); while (!mIsServiceDestoryed) { String str = in.readLine(); Log.i(TAG, str); if (str == null) { break; } int i = new Random().nextInt(mDefinedMessages.length); String msg = mDefinedMessages[i]; out.println(msg);//服务端返回的消息 写入输出流 Log.i(TAG, msg); } Log.i(TAG, "Quit"); out.close(); in.close(); client.close(); } }
客户端代码
public class TCPClientActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "xbh"; private static final int MESSAGE_RECEIVE_NEW_MSG = 1; private static final int MESSAGE_SOCKET_CONNECTED = 2; private Button mSendButton; private TextView mMessageTextView; private EditText mMessageEditText; private PrintWriter mPrintWriter; private Socket mClientSocket; private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MESSAGE_RECEIVE_NEW_MSG: { mMessageTextView.setText(mMessageTextView.getText() + (String) msg.obj); break; } case MESSAGE_SOCKET_CONNECTED: { mSendButton.setEnabled(true); break; } } return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tcpclient); mMessageTextView = findViewById(R.id.msg_container); mSendButton = findViewById(R.id.send); mSendButton.setOnClickListener(this); mMessageEditText = findViewById(R.id.msg); Intent service = new Intent(this, TCPServerService.class); startService(service); new Thread() { @Override public void run() { connectTCPServer(); } }.start(); } @Override protected void onDestroy() { if (mClientSocket != null) { try { mClientSocket.shutdownInput(); mClientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } super.onDestroy(); } @Override public void onClick(View v) { if (v == mSendButton) { final String msg = mMessageEditText.getText().toString(); if (!TextUtils.isEmpty(msg) && mPrintWriter != null) { mPrintWriter.println(msg); mMessageEditText.setText(""); String time = formatDateTime(System.currentTimeMillis()); final String showedMsg = "self" + time + ":" + msg + "\n"; mMessageTextView.setText(mMessageTextView.getText() + showedMsg); } } } @SuppressLint("SimpleDateFormat") private String formatDateTime(long time) { return new SimpleDateFormat("(HH:mm:ss)").format(new Date(time)); } private void connectTCPServer() { Socket socket = null; //分别从socket中取出了输出流和输入流 while (socket == null) { try { socket = new Socket("localhost", 8688); mClientSocket = socket; mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);//代表连接上了 Log.i(TAG, "connect success"); } catch (IOException e) { e.printStackTrace(); Log.i(TAG, "connect failed "+e.getMessage()); } } BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (!TCPClientActivity.this.isFinishing()) { String msg = br.readLine(); Log.i(TAG, msg); if (msg != null) { String time = formatDateTime(System.currentTimeMillis()); final String shoeMsg = "server" + time + ":" + msg + "\n"; //Handler的作用仅仅是切换线程,更新UI 整个逻辑很简单,不断从输入流和输出流中取。这个方法运行在子线程中,所以不会ANR mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, shoeMsg).sendToTarget(); } } Log.i(TAG, "Quit"); mPrintWriter.close(); br.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
相关文章推荐
- android 跨进程通信 LocalServerSocket LocalSocket Address already in use
- android Socket实现多进程通信,互动
- Android中LocalSocket使用 进程通信
- android 跨进程通信 LocalServerSocket LocalSocket Address already in use
- Android 进阶12:进程通信之 Socket (顺便回顾 TCP UDP)
- Android之进程通信机制(下)(AIDL,Messenger,Socket)
- [Android进阶]之深入了解通信协议:http、TCP/IP协议与socket之间的区别
- Android之Socket通信、List加载更多、Spinner下拉列表
- Android local socket 进程间通讯实验
- Android系统使用socket在Java层和native之间数据通信
- Android IPC进程通信 Messager方式
- Android进阶——Socket长连接通信实例
- Android中Socket通信
- Android 使用mina框架 搭建socket客户端,进行与服务器端通信
- QT单实例应用,使用QLocalSocket进行进程通信,不同运行权限下运行的同一个进程通讯失败,报错 “QLocalSocket::SocketAccessError”
- [Android通信]基于socket的聊天app(三):传输json数据
- [Android通信]基于socket的聊天app(五):收发表情
- Android进程通信机制之-aidl">安卓进程通信机制之 AIDL
- Android与PC之间Socket通信
- socket编程的理解-------解决不同主机上进程之间的通信