各位看官们,大家好,上一回中咱们说的是Android中网络通信之TCP客户端的例子,这一回中咱们说的例子是网络通信之TCP通信模型。闲话休提,言归正转。让我们一起Talk Android吧!

看官们,我们在上一回中通过具体的代码演示了如何进行TCP通信,不过这种通信属于最基本的通信,在实际项目中还需要添加通信模型。本章回中介绍迭代模型,也就是多个客户端同时与一个服务器进行通信。下面是该模型的示意图:

只有文字和图像不足以了解迭代模型,下面我们通过文字结合代码的方法来介绍迭代模型:

服务端演示

我们先定义T8Server2类,并且定义该类的构造方法,构造方法中包含一个参数表示服务器的端口,通过构造方法可以创建一个服务器对象。

我们在类中定义了acceptConnectRequest()方法,该方法封装了accept()方法,主要用来接受客户端发起的连接请求并且与客户端建立连接。

我们在类中定义了disconnectClient()方法,该方法封装了close()方法,主要用来断开服务端和客户端之间的TCP连接。

我们在类中定义传输数据的方法sendDataToClient()和getDataFromClient(),这两个方法使用了IO流来发送和接收数据,发送和接收数据时使用了字节流和字符流两种不同的方法,因此部分代码有注释,其中的细节我们就不详细了,大家可以参考下面的代码。

这些内容和上一章回的完全相同,不同之处有三点:类名、每次都获取输入流、使用字符流而不是字节流读取socket中的数据。如果大家对上一章回的内容比较熟悉,只关注这三个细节方面的差异就可以。

此外,上一章回中的代码注释把字节流和字符流写反了,在这里做个修正。

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.PrintStream;public class T8Server2 {private Socket mSocket;private ServerSocket mServerSocket;private int mPort;private InputStream mSocketInputStream;private OutputStream mSocketOutputStream;public T8Server2 (int port) {mPort = port;try {mServerSocket = new ServerSocket(mPort);}catch(Exception e) {e.printStackTrace();}}public void acceptConnectRequest() {if(mServerSocket != null) {try {if(!mServerSocket.isClosed()) {mSocket = mServerSocket.accept();System.out.println("Server accept the request of Client");}}catch(Exception e) {e.printStackTrace();}}}public void disconnectClient() {if(mServerSocket!= null && !mServerSocket.isClosed()) {try {if(mSocketInputStream != null)mSocketInputStream.close();if(mSocketOutputStream != null)mSocketOutputStream.close();mServerSocket.close();mServerSocket = null;}catch (IOException e) {e.printStackTrace();}}}public void sendDataToClient(String data) {PrintStream printStream = null;try {if(mSocketOutputStream == null) {mSocketOutputStream = mSocket.getOutputStream();}if(printStream == null) {printStream = new PrintStream(mSocketOutputStream);}printStream.println(data);// mSocketOutputStream.write(data.getBytes());// mSocketOutputStream.flush();}catch (IOException e) {e.printStackTrace();}}public String getDataFromClient() {String data = null;BufferedReader bufferedReader = null;StringBuilder strTemp = new StringBuilder();byte [] bytes = new byte[1024];char [] charByte = new char[512];try {if(mSocket != null && mSocket.isConnected()) {mSocketInputStream = mSocket.getInputStream();//get data by character streamnew InputStreamReader(mSocketInputStream).read(charByte);data = String.valueOf(charByte);}//get data by byte stream// if(bufferedReader == null) {//  bufferedReader = new BufferedReader(new InputStreamReader(mSocketInputStream));// }// data = bufferedReader.readLine();}catch (IOException e) {e.printStackTrace();}return data;}}

客户端演示

我们先定义T8Client2类,并且定义该类的构造方法,构造方法中包含三个参数,分别表示服务器的IP地址、端口和客户端的ID,通过构造方法可以创建一个客户端对象。

我们在类中定义了connectServer()方法,该方法封装了connect()方法,主要用来向服务端发起连接请求。

我们在类中定义了disconnectServer()方法,该方法封装了close()方法,主要用来断开服务端和客户端之间的TCP连接。

我们在类中定义传输数据的方法sendDataToServer()和getDataFromSever(),这两个方法使用了IO流来发送和接收数据,发送和接收数据时使用了字节流和字符流两种不同的方法,因此部分代码有注释,其中的细节我们就不详细了,大家可以参考下面的代码。

最后我们添加一个方法用来启动线程,在程序中做“连接服务器"和"发送数据到服务器"的操作;

这些内容和上一章回的内容大部分相同,不同之处有两点:构造方法多了一个参数;启动线程的方法是新添加的。

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.PrintStream;public class T8Client2 {private String strAddress;private Socket mSocket;private String mHost;private int mPort;private String mID;private InetAddress remoteAddr;private SocketAddress mSocketAddress;private InputStream mSocketInputStream;private OutputStream mSocketOutputStream;private Thread mThead;public T8Client2 (String addr, int port,String id) {try {strAddress = addr;mPort = port;mID =id;remoteAddr = InetAddress.getByName(strAddress);mSocketAddress = new InetSocketAddress(remoteAddr,mPort);mSocketOutputStream = null;mSocketInputStream = null;} catch(Exception e) {e.printStackTrace();}try {mSocket = new Socket();}catch(Exception e) {e.printStackTrace();}}public void connectServer() {int timeOut = 5000;try {mSocket.connect(mSocketAddress,timeOut);System.out.println("Client connect to Server successfully");}catch (Exception e) {e.printStackTrace();}}public void disconnectServer() {if(mSocket != null && mSocket.isConnected()) {try {if(mSocketInputStream != null)mSocketInputStream.close();if(mSocketOutputStream != null)mSocketOutputStream.close();mSocket.close();}catch (IOException e) {e.printStackTrace();}}}public boolean isConnected() {boolean result = false;if(mSocket != null) {if( mSocket.isConnected())result = true;}return result;}public void sendDataToServer(String data) {PrintStream printStream = null;try {if(mSocketOutputStream == null) {mSocketOutputStream = mSocket.getOutputStream();}if(printStream == null) {printStream = new PrintStream(mSocketOutputStream);}// printStream.println(data);mSocketOutputStream.write(data.getBytes());// mSocketOutputStream.flush();}catch (IOException e) {e.printStackTrace();}}public String getDataFromSever() {String data = null;BufferedReader bufferedReader = null;StringBuilder strTemp = new StringBuilder();byte [] bytes = new byte[512];try {if(mSocketInputStream == null) {mSocketInputStream = mSocket.getInputStream();}mSocketInputStream.read(bytes);if(bufferedReader == null) {bufferedReader = new BufferedReader(new InputStreamReader(mSocketInputStream));}data = bufferedReader.readLine();}catch (IOException e) {e.printStackTrace();}// for(byte item : bytes) {//    strTemp.append(String.format("%s", item));// }// data = strTemp.toString();return data;}public void startRunning() {mThead = new Thread(new Runnable () {@Overridepublic void run() {connectServer();sendDataToServer(mID);}});mThead.start();}}

TCP通信演示

我们创建一个包含main方法的类,用它来当作控制TCP通信的主程序。在main方法中先创建服对象。因为TCP通信过程中会阻塞主线程,也就是main方法所在在线程,所以我们创建了一个子线程,用来表示服务端。在服务端线程中主要是监听客户端发来的连接请求,在接受连接请求后接收客户端发来的数据,接收完最后一条数据后关闭TCP连接。

接着创建五个客户端对象,并且添加到数组中,接着依次调用客户端的startRunning()方法来启动线程,线程启动后,客户端会向服务端发起连接并且发送数据到服务端。

这里一共有五个客户端并且每个客户端都对应一个线程,这相当于有五个客户端同时在和服务器进行TCP通信。为了方便演示,我们在启动每个客户端的线程之间添加了延时。

我们在客户端向服务端发送的数据是客户端的ID,比如:“Client3”,在程序运行时可以看到。注意需要先启动服务端线程后再启动客户端线程。下面是该类的代码,请大家参考:


import java.util.ArrayList;public class TCPEx2 {public static void main(String args[]) {String serverAddress = "127.0.0.1";int serverPort = 8009;T8Server2 mServer;T8Client2 mClient;Thread mServerThread;Thread mClientThread;ArrayList<T8Client2> clientGroup = new ArrayList<T8Client2>();mServer = new T8Server2(serverPort);mServerThread = new Thread( new Runnable() {@Overridepublic void run() {boolean flag = true;String data = null;while(flag) {if(mServer != null) mServer.acceptConnectRequest();data = mServer.getDataFromClient();System.out.println("---> Server get data < "+data+" > form Client.");System.out.println();if(data.contains("5")) {flag = false;}}System.out.println("---> server stop running...");mServer.disconnectClient();}});mServerThread.start();for(int i=0; i<5; i++) {String id = String.valueOf(i+1);id = "Client"+id;mClient = new T8Client2(serverAddress,serverPort,id);clientGroup.add(mClient);mClient = null;}for(int i=0; i<clientGroup.size();i++) {mClient = clientGroup.get(i);System.out.println("<-- Client["+i+"] send request to Server.");mClient.startRunning();mClient = null;try {Thread.sleep(100);} catch(InterruptedException e) {e.printStackTrace(); } }}}

在控制台中编译并且运行这三个类,可以得到以下结果:

$ javac T8Client2.java T8Server2.java TCPEx2.java$ java TCPEx2
<-- Client[0] send request to Server.
Client connect to Server successfully
Server accept the request of Client
---> Server get data < Client1 > form Client.<-- Client[1] send request to Server.
Client connect to Server successfully
Server accept the request of Client
---> Server get data < Client2 > form Client.<-- Client[2] send request to Server.
Client connect to Server successfully
Server accept the request of Client
---> Server get data < Client3 > form Client.<-- Client[3] send request to Server.
Client connect to Server successfully
Server accept the request of Client
---> Server get data < Client4 > form Client.<-- Client[4] send request to Server.
Client connect to Server successfully
Server accept the request of Client
---> Server get data < Client5 > form Client.---> server stop running...

看官们,关于Android中网络通信之TCP通信模型的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

一起Talk Android吧(第三百二十四回:Android中网络通信之TCP通信模型一)相关推荐

  1. 第三百二十四节,web爬虫,scrapy模块介绍与使用

    第三百二十四节,web爬虫,scrapy模块介绍与使用 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为 ...

  2. 第三百二十六节,web爬虫,scrapy模块,解决重复ur——自动递归url

    第三百二十六节,web爬虫,scrapy模块,解决重复url--自动递归url 一般抓取过的url不重复抓取,那么就需要记录url,判断当前URL如果在记录里说明已经抓取过了,如果不存在说明没抓取过 ...

  3. 第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签...

    第三百二十五节,web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签 标签选择器对象 HtmlXPathSelector()创建标签选择器对象,参数接收response回调的html对象 ...

  4. 美学心得(第二百二十四集)罗国正

    美学心得(第二百二十四集) 罗国正 (2021年7月) 2987.清朝画家方士庶认为:绘画是"于天地之外,别构一种灵奇"."因心造境,以手运心"."山 ...

  5. 二十四、Struts2中的UI标签

    二十四.Struts2中的UI标签 Struts2中UI标签的优势: 数据回显 页面布局和排版(Freemark),struts2提供了一些常用的排版(主题:xhtml默认 simple ajax) ...

  6. Android开发笔记(一百二十四)自定义相册

    画廊Gallery Gallery是一个早期的画廊控件,左右滑动手势可展示内嵌的图片列表,类似于一个平面的万花筒.虽然Android现在将Gallery标记为Deprecation(表示已废弃),建议 ...

  7. 不朽凡人 第四百二十四章 再回半仙域

    莫无忌笑了笑,"两位道友倒是和我一样,我也是得罪了洪斧及,这才来到这里." "那我们联合在一起,我们这边有了六个人,我相信离开死亡矿区也有生存之地了."听到莫无 ...

  8. 一起Talk Android吧(第三百七十九回:让ViewPager一屏幕显示三页)

    文章目录 概念介绍 实现原理 操作步骤 示例程序 各位看官们,大家好,上一回中咱们说的是给ViewPager添加indicator的例子,这一回中咱们介绍的例子是让ViewPager一屏显示三页.闲话 ...

  9. Android Multimedia框架总结(二十四)MediaMuxer实现手机屏幕录制成gif图

    原址:http://blog.csdn.net/hejjunlin/article/details/53866405 前言:上篇中,介绍是用MediaMuxer与MediaExtractor进入音视频 ...

最新文章

  1. PowerEdge R730安装Windows server2008 R2操作系统
  2. Leetcode 113. 路径总和 II 解题思路及C++实现
  3. C++中的野指针问题
  4. operation 多线程
  5. python概念-Socket到底有多骚
  6. SQL SERVER 2005 数据挖掘与商业智能完全解决方案---学习笔记(二)
  7. linux查看文件时显示行号,linux中查看文件时显示行号
  8. 计算机应用离散数学,结合计算机应用的离散数学教学研究.pdf
  9. Android--扫一扫(识别二维码、条码)
  10. 吃猕猴桃,当然不不不不能错过贵州的啦
  11. QQ邮箱开通exchange的方法
  12. 联想 x系列服务器停产,去年年底惠普、IBM和联想相继在服务器市场失去了份额...
  13. android手机赚钱软件排行
  14. lisp不是函授型语言_讨论:为什么Lisp语言不再被广泛使用
  15. 预训练模型 Fine-tuning
  16. interlay: IBC bridge BTC to Cosmos
  17. [SAP] 生产订单报错SEQ_NOT_FOUND/OPR_NOT_FOUND问题解决
  18. Android 蓝牙开发——Avrcp协议(十二)
  19. matlab平衡小车数学模型PID,自平衡小车控制系统设计.doc
  20. 惠普台式计算机配置,hp台式机bios设置方法

热门文章

  1. 数据掘金:电子商务运营突围
  2. 常用网站木马文件后门检测工具
  3. 制作和合入quilt补丁
  4. 数据结构单链表的基础操作(C语言)
  5. Qt Phonon介绍及安装
  6. 什么叫反光识别读数识别_反光识别和读数识别是什么意思 反光膜 反光镜 反光材料...
  7. 毕业学生就业数据可视化平台。
  8. Windows下安装图片标注工具LabelImg遇到的问题及解决办法
  9. 这一次,Google 誓要扎根中国了!
  10. 感兴趣的很多,擅长的却没一个