一起Talk Android吧(第三百二十四回:Android中网络通信之TCP通信模型一)
Posted talk_8
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起Talk Android吧(第三百二十四回:Android中网络通信之TCP通信模型一)相关的知识,希望对你有一定的参考价值。
各位看官们,大家好,上一回中咱们说的是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 stream
new 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 ()
@Override
public 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()
@Override
public 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通信模型一)的主要内容,如果未能解决你的问题,请参考以下文章
一起Talk Android吧(第三百四十四回: JSON概述)
一起Talk Android吧(第三百二十六回:Android中的布局编辑器)
一起Talk Android吧(第三百一十四回:ImageView常用属性三)
一起Talk Android吧(第三百三十四回: Android中的HTTP请求一)