各位看官们,大家好,上一回中咱们说的是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();
}
}
我们创建一个包含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通信模型的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!