Constructing efficient multi-protocol Android communication framework based on thread pool and NIO technology

Source: Internet
Author: User
In most mobile applications involving network communication, because the speed of GPRS network is not ideal in the present situation, how to efficiently request the network data becomes the bottleneck problem that most applications face. At the same time, in some applications may use a variety of protocols, such as IM communications, video stream types of applications will sacrifice data integrity to more efficient access to data, in this type of application, may need to support both TCP, UDP and HTTP protocol. In this paper, we try to build a framework based on Android Multithread Technology Threadpoolexecutor and NIO non-blocking programming to efficiently obtain network data and support multiple protocol concurrent requests.

Basic design Ideas
Since it is based on the threadpoolexecutor thread pool to manage requests for multiple NIO threads, there should first be a global threadpoolexecutor variable, which is implemented using a single case pattern:
public static synchronized Threadpoolexecutor setthreadpoolnum (int athreadpoolminnum,
int Athreadpoolmaxnum,long KeepAliveTime)
{
if (ThreadPool = null)
{
ThreadPool =
New Threadpoolexecutor (Athreadpoolminnum,athreadpoolmaxnum,
Keepalivetime,timeunit.seconds,new arrayblockingqueue<runnable> (3),
New Threadpoolexecutor.discardoldestpolicy ());
}

return threadPool;
}
Each NIO request is designed as a separate thread, and each network communication connection can be attached to the NIO thread, and the basic design ideas are as follows:


Design of NIO Communication threads
NIO communication threads are designed to manage multiple different types of network connections and are responsible for maintaining network data processing interfaces for each connection, including data-sending interfaces Processwrite (), data-receiving interfaces Processread () and error Handling Interface Processerror () and so on.
After each NIO communication thread is started by the thread pool object, first check that the NIO port has a connection registration data arrival, and if any data arrives, submit it to the appropriate connection for processing, the code reads as follows:
try {
if (selector!= null)
n = selector.select (3000);
If you want to shutdown, close selector exit
if (shutdown) {
Selector.close ();
Break
}
catch (IOException e) {
Dispatcherrortoall (e);
}
If the select returns greater than 0, the event is handled
if (n > 0) {
for (Iterator<selectionkey> i = Selector.selectedkeys (). iterator (); I.hasnext ();) {
Get the next key
Selectionkey SK = I.next ();
I.remove ();
Check that it is still valid
if (!sk.isvalid ())
Continue

Processing
Iniohandler handler = (Iniohandler) sk.attachment ();
try {
if (sk.isconnectable ())
{
Handler.processconnect (SK);
}
else if (sk.isreadable ())
{
Handler.processread (SK);
}
catch (IOException e) {
Handler.processerror (e);
catch (RuntimeException e) {
}
}
n = 0;
}
Checknewconnection ();
Notifysend ();
The code above first uses the Selectedkyes () method of the Selector class to get all the connection channels that have event occurrences, then iterate through the channels, and use the attachment () method to obtain the processing object Niohandler registered to the channel. It then invokes the method of the Niohandler object registered on each connection channel to process the network data.
The design of network connection
Knowing from the design of the NIO communication threads that each network connection has a corresponding connection channel and a data processor connecting the channel, you can abstract the interfaces of these connection channels and the data processor:
Public interface Iconnection {
/**
* Add a package to the Send queue
*
* @param out
* Outpacket Sub Class
*/
public void Add (Outpacket out);

public void Clearsendqueue ();

public void start ();

Public String getId ();

public void Dispose ();

Public inetsocketaddress getremoteaddress ();

Public Selectablechannel channel ();

Public Iniohandler Getniohandler ();

public Boolean isempty ();

public void receive () throws IOException;

public void Send () throws IOException;

public void Send (Bytebuffer buffer);

public boolean isconnected ();
}
In the channel data processor, each connection channel should have basic data sending, data receiving and error handling interfaces, and the basic interface of the data processor can be abstracted as follows:
Public interface Iniohandler {
public void Processconnect (Selectionkey sk) throws IOException;

public void Processread (Selectionkey sk) throws IOException;

public void Processwrite () throws IOException;

public void Processerror (Exception e);
}
Then each network connection should inherit the above two interfaces, for example, the TCP connection needs to have the Socketchannel channel and the corresponding Niohandler data processing interface. The UDP connection requires a Datagramchannel channel and the corresponding Niohandler data processing interface, the following is the code for Tcpconnection:
public class Tcpconnection extends connectionimp{

/** for communication channel * *
Private final Socketchannel channel;
/**
* True indicates that this connection has been closed remotely
*/
Private Boolean remoteclosed;

/**
* Constructs a tcpport that is connected to the specified address.
*
* addresses to which @param address is connected.
* @throws IOException Port Open/port Configuration/connection to address error.
*/
Public tcpconnection (String ID, inetsocketaddress address) throws IOException {
Super (ID);
Channel = Socketchannel.open ();
Channel.configureblocking (FALSE);
this.remoteaddress = address;
remoteclosed = false;
}

public void Start () {
try {
Channel.connect (remoteaddress);
catch (Unknownhostexception e) {
Processerror (New Exception ("Unknown Host"));
catch (Unresolvedaddressexception e) {
Processerror (New Exception ("Unable to resolve server address"));
catch (IOException e) {
Processerror (e);
}
}

Public Selectablechannel Channel () {
return channel;
}

public void receive () throws IOException {
if (remoteclosed)
Return
Receive data
int oldpos = Receivebuf.position ();
for (int r = channel.read (RECEIVEBUF); r > 0; r = Channel.read (RECEIVEBUF))
;

byte[] Tempbuffer = new byte[1024];
Receivebuf.get (tempbuffer, 0, Receivebuf.position ());
LOG.E ("Receive", "=" +new String (Tempbuffer, "UTF-8"));

Get Current position
int pos = Receivebuf.position ();
Receivebuf.flip ();
Check to see if 0 bytes have been read, which generally means that the connection has been shut down remotely
if (Oldpos = = pos) {
Remoteclosed = true;
Return
}
Inpacket packet = new Inpacket (RECEIVEBUF);
Inqueue.add (packet);

Adjustbuffer (POS);
}

private void Adjustbuffer (int pos) {
If 0 is not equal to the current POS, the description analyzes at least one package
if (receivebuf.position () > 0) {
Receivebuf.compact ();
Receivebuf.limit (Receivebuf.capacity ());
} else {
Receivebuf.limit (Receivebuf.capacity ());
Receivebuf.position (POS);
}
}

public void Send () throws IOException {
while (!isempty ()) {
Sendbuf.clear ();
Outpacket packet = remove ();
Channel.write (Bytebuffer.wrap (Packet.getbody ()));
Add to the postback queue
Packet.settimeout (System.currenttimemillis () + enginconst.qq_timeout_send);
LOG.E ("Debug", "Have sended packet-" + packet.tostring ());
}
}

public void Send (Outpacket packet) {
try {
Sendbuf.clear ();
Channel.write (Bytebuffer.wrap (Packet.getbody ()));
LOG.D ("Debug", "Have sended packet-" + packet.tostring ());
catch (Exception e) {
}
}

public void Send (Bytebuffer buffer) {
try {
Channel.write (buffer);
catch (IOException e) {
}
}

public void Dispose () {
try {
Channel.close ();
catch (IOException e) {
}
}

public boolean isconnected () {
Return channel!= null && channel.isconnected ();
}

public void Processconnect (Selectionkey sk) throws IOException {
Completing the Socketchannel connection
Channel.finishconnect ();
while (!channel.isconnected ()) {
try {
Thread.Sleep (300);
catch (Interruptedexception e) {
}
Channel.finishconnect ();
}
Sk.interestops (Selectionkey.op_read);
LOG.E ("Debug", "Hava connected to Server");
}

public void Processread (Selectionkey sk) throws IOException {
Receive ();
}
public void Processwrite () throws IOException {
if (isconnected ())
Send ();
}
}
Test code
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Asyncrequest request = new Asyncrequest (New Inetsocketaddress ("10.0.2.2", 8042);
try {
Request.setconnumperniothread (5);
Asyncrequest.setthreadpoolnum (2, 5, 2);
REQUEST.SETUDP (FALSE);
Request.setbody ("Hello World". GetBytes ());
Request.startasyn (0);

if (!request.iscurrrequestfull ())
{
Request.setbody ("My name is Dongfengsun". GetBytes ());
Request.startasyn (1);
}
catch (Exception e) {
LOG.E ("OnCreate", "=" +e.getmessage ());
E.printstacktrace ();
}
}

The maximum connection limit for each NIO communication thread is set at 5 in the test code, and if each NIO communication thread has a free number of connections, you can continue to create a network connection on the current NIO communication thread and, if full, reinitialize a NIO communication thread and join the thread pool

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.