Android IPC机制(五)用Socket实现跨进程聊天程…
2018-07-11 03:55:18来源:博客园 阅读 ()
1.Socket简介
Socket也称作“套接字“,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。它分为流式套接字和数据包套接字,分别对应网络传输控制层的TCP和UDP协议。TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。它使用三次握手协议建立连接,并且提供了超时重传机制,具有很高的稳定性。UDP协议则是是一种无连接的协议,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多。
从上图我们也可以看出,不同的用户进程通过Socket来进行通信,所以Socket也是一种IPC方式,接下来我们用TCP服务来实现一个简单的聊天程序。
2.实现聊天程序服务端
配置
首先我们来实现服务端,当然要使用Socket我们需要在AndroidManifest.xml声明如下的权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
我们需要实现一个远程的Service来当作聊天程序的服务端,AndroidManifest.xml文件中配置service:
<service android:name=".SocketServerService" android:process=":remote" />
实现Service
接下来我们在Service启动时,在线程中建立TCP服务,我们监听的是8688端口,等待客户端连接,当客户端连接时就会生成Socket。通过每次创建的Socket就可以和不同的客户端通信了。当客户端断开连接时,服务端也会关闭Socket并结束结束通话线程。服务端首先会向客户端发送一条消息:“您好,我是服务端”,并接收客户端发来的消息,将收到的消息进行加工再返回给客户端。
package com.example.liuwangshu.moonsocket; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; 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.net.ServerSocket; import java.net.Socket; public class SocketServerService extends Service { private boolean isServiceDestroyed = false; @Override public void onCreate() { new Thread(new TcpServer()).start(); super.onCreate(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } private class TcpServer implements Runnable { @Override public void run() { ServerSocket serverSocket; try { //监听8688端口 serverSocket = new ServerSocket(8688); } catch (IOException e) { return; } while (!isServiceDestroyed) { 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 (!isServiceDestroyed) { String str = in.readLine(); Log.i("moon", "收到客户端发来的信息" + str); if (TextUtils.isEmpty(str)) { //客户端断开了连接 Log.i("moon", "客户端断开连接"); break; } String message = "收到了客户端的信息为:" + str; // 从客户端收到的消息加工再发送给客户端 out.println(message); } out.close(); in.close(); client.close(); } @Override public void onDestroy() { isServiceDestroyed = true; super.onDestroy(); } }
3.实现聊天程序客户端
客户端Activity会在onCreate方法中启动服务端,并开启线程连接服务端Socket。为了确保能连接成功,采用了超时重连的策略,每次连接失败时都会重新建立连接。连接成功后,客户端会收到服务端发送的消息:“您好,我是服务端”,我们也可以在EditText输入字符并发送到服务端。
package com.example.liuwangshu.moonsocket; import android.content.Intent; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; 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.net.Socket; public class SocketClientActivity extends AppCompatActivity { private Button bt_send; private EditText et_receive; private Socket mClientSocket; private PrintWriter mPrintWriter; private TextView tv_message; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_socket); initView(); Intent service = new Intent(this, SocketServerService.class); startService(service); new Thread() { @Override public void run() { connectSocketServer(); } }.start(); } private void initView() { et_receive= (EditText) findViewById(R.id.et_receive); bt_send= (Button) findViewById(R.id.bt_send); tv_message= (TextView) this.findViewById(R.id.tv_message); bt_send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String msg = et_receive.getText().toString(); //向服务器发送信息 if(!TextUtils.isEmpty(msg)&&null!=mPrintWriter) { mPrintWriter.println(msg); tv_message.setText(tv_message.getText() + "\n" + "客户端:" + msg); et_receive.setText(""); } } }); } private void connectSocketServer() { Socket socket = null; while (socket == null) { try { //选择和服务器相同的端口8688 socket = new Socket("localhost", 8688); mClientSocket = socket; mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); } catch (IOException e) { SystemClock.sleep(1000); } } try { // 接收服务器端的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (!isFinishing()) { final String msg = br.readLine(); if (msg != null) { runOnUiThread(new Runnable() { @Override public void run() { tv_message.setText(tv_message.getText() + "\n" + "服务端:" + msg); } } ); } } mPrintWriter.close(); br.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
布局很简单(activity_socket.xml):
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_message" android:layout_width="match_parent" android:layout_height="400dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:orientation="horizontal"> <EditText android:id="@+id/et_receive" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" /> <Button android:id="@+id/bt_send" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="向服务器发消息" /> </LinearLayout> </RelativeLayout>
4.运行聊天程序
运行程序,我们可以看到客户端和服务端是两个进程:
客户端首先会收到服务端的信息:”您好,我是服务端”,接下来我们向服务端发送“我想要怒放的生命”。这时候服务端收到了这条信息并返回给客户端加工后的这条信息:
https://github.com/henrymorgen/MoonSocket
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:网页自适应
下一篇:WEB相关背景知识(新手)
- 1.Android网络编程-HTML介绍 2020-02-07
- 关于css中的基本定位机制 2019-08-14
- float浮动-清浮动BFC渲染机制 2019-02-17
- Cookie/Session机制详解 2018-06-24
- ios下引用MUI后input不能输入,Android端正常 2018-06-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash