使用Socket处理跨进程的实时聊天
2016-06-30 18:20
591 查看
欢迎Follow我的GitHub, 关注我的CSDN.
Socket是套接字, 网络通信经常使用的方法, 分为TCP和UDP两种模式, 需要网络权限, 当然也可以应用于跨进程通信. 本文通过一个简易的Android聊天程序, 熟悉Socket的使用方法.
本文源码的GitHub下载地址
逻辑: 客户端向服务端发送数据, 服务端收到后返回客户端数据.
TCP服务的Socket链接. 设置Socket的端口号
处理Socket数据, 使用
服务器使用单独线程, 模拟跨进程通信.
需要申请网络权限, 连网和访问网络状态.
启动服务, 连接TCP服务器.
尝试连接服务器, 每隔1秒进行重试, 并初始化发送缓存
成功后, 循环调用, 监听
Handler处理数据, 分为连接成功和获取数据两种情况.
点击按钮发送数据, 直接在PrintWriter中写入, 即可.
当我们向服务端发送数据时, 就会获取服务端的返回, 模拟聊天效果.
效果
Socket作为经典的网络通信方式, 有很多应用, 也可以实现跨进程通信, 希望能熟练掌握.
OK, that’s all! Enjoy it!
Socket是套接字, 网络通信经常使用的方法, 分为TCP和UDP两种模式, 需要网络权限, 当然也可以应用于跨进程通信. 本文通过一个简易的Android聊天程序, 熟悉Socket的使用方法.
本文源码的GitHub下载地址
逻辑: 客户端向服务端发送数据, 服务端收到后返回客户端数据.
Server
Socket处理属于网络请求, 需要在其他线程中使用, 不能应用于主线程.new Thread(new TcpServer()).start();
TCP服务的Socket链接. 设置Socket的端口号
ServerSocket(PORT), 不断循环的接收数据
serverSocket.accept(), 在
responseClient()方法处理数据.
private class TcpServer implements Runnable { @Override public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(PORT); } catch (IOException e) { Log.e(TAG, "建立链接失败, 端口:" + PORT); e.printStackTrace(); return; // 链接建立失败直接返回 } while (!mIsServiceDestroyed) { try { final Socket client = serverSocket.accept(); Log.e(TAG, "接收数据"); new Thread() { @Override public void run() { try { responseClient(client); } catch (IOException e) { e.printStackTrace(); } } }.start(); } catch (IOException e) { e.printStackTrace(); } } } }
mIsServiceDestroyed用于判断服务器是否存活, 防止内存泄露.
处理Socket数据, 使用
BufferedReader读取数据, 使用
PrintWriter写入数据, 循环检测, 结束时关闭缓存和Socket.
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("欢迎欢迎, 我是Spike!"); while (!mIsServiceDestroyed) { String str = in.readLine(); Log.e(TAG, "信息来自: " + str); if (str == null) { break; } int i = new Random().nextInt(mDefinedMessages.length); String msg = mDefinedMessages[i]; out.println(msg); Log.e(TAG, "发送信息: " + msg); } System.out.println("客户端退出"); // 关闭通信 close(out); close(in); client.close(); }
服务器使用单独线程, 模拟跨进程通信.
<service android:name=".TCPServerService" android:process=":remote"/>
需要申请网络权限, 连网和访问网络状态.
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Client
客户端, 向服务器发送数据, 并接收服务器返回的数据.启动服务, 连接TCP服务器.
Intent intent = new Intent(this, TCPServerService.class); startService(intent); new Thread(new Runnable() { @Override public void run() { connectTCPServer(); } }).start();
尝试连接服务器, 每隔1秒进行重试, 并初始化发送缓存
PrintWriter.
Socket socket = null; // 不停重试直到连接成功为止 while (socket == null) { try { socket = new Socket("localhost", TCPServerService.PORT); mClientSocket = socket; mPrintWriter = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED); Log.e(TAG, "服务器连接成功"); } catch (IOException e) { SystemClock.sleep(1000); Log.e(TAG, "连接TCP服务失败, 重试..."); } }
成功后, 循环调用, 监听
BufferedReader, 是否有数据返回.
BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream())); while (!MainActivity.this.isFinishing()) { String msg = br.readLine(); Log.e(TAG, "收到信息: " + msg); if (msg != null) { String time = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH).format(System.currentTimeMillis()); String showedMsg = "server " + time + ":" + msg + "\n"; mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showedMsg) .sendToTarget(); } }
Handler处理数据, 分为连接成功和获取数据两种情况.
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_RECEIVE_NEW_MSG: mTvContent.setText( String.valueOf(mTvContent.getText().toString() + msg.obj)); break; case MESSAGE_SOCKET_CONNECTED: mBSend.setEnabled(true); break; default: break; } } };
点击按钮发送数据, 直接在PrintWriter中写入, 即可.
public void sendMessage(View view) { String msg = mEtMessage.getText().toString(); if (!TextUtils.isEmpty(msg) && mPrintWriter != null) { mPrintWriter.println(msg); mEtMessage.setText(""); String time = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH).format(System.currentTimeMillis()); String showedMsg = "self " + time + ":" + msg + "\n"; mTvContent.setText(String.valueOf(mTvContent.getText() + showedMsg)); } }
当我们向服务端发送数据时, 就会获取服务端的返回, 模拟聊天效果.
效果
Socket作为经典的网络通信方式, 有很多应用, 也可以实现跨进程通信, 希望能熟练掌握.
OK, that’s all! Enjoy it!
相关文章推荐
- java-模拟tomcat服务器
- Linux socket 初步
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析