Non-Blocking mode for UDP
Non-Blocking UDP 指令使用方法如下:
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
public class NIOUDPProcess
{
private String mRemote_IP = "";
private String mRemote_Port = "";
private String mReceive_Message = "";
private int mSenderPort = -1;
private Thread udpClientThread,udpReceiverThread,udpSenderThread;
private int MAX_PACKET_SIZE = 1024;
private boolean isRunning = false;
private Context mContext;
private DatagramChannel mSenderChannel,mReceiverChannel,mChannel;
private DatagramSocket mSenderSocket;
private SocketAddress mSenderAddress;
public static interface NIOUDPStatusListener
{
void displayMessage(String message);
}
NIOUDPStatusListener mServerStatusListenerCallback;
public NIOUDPProcess(Context context, NIOUDPStatusListener callback)
{
mContext = context;
mServerStatusListenerCallback = callback;
}
/**
* Start NIO receiver process thread.
* @param The port for binding and how many lines you want to bind.
* @return
*/
public void startNIOUDPReceiverProcess(final int bind_port ,final int number)
{
udpReceiverThread = new Thread(new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
Selector mSelector = Selector.open();
int port = bind_port;
for(int i = 0; i < number; i++)
{
mReceiverChannel = DatagramChannel.open( );
mReceiverChannel.configureBlocking(false);
mReceiverChannel.socket().bind(new InetSocketAddress(port));
mReceiverChannel.register(mSelector, SelectionKey.OP_READ);
port++;
}
isRunning = true;
ByteBuffer mReceiveBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
while(isRunning)
receiveProcess(mReceiveBuffer, mSelector);
}
catch (SocketException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Open socket error.");
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Bind socket error.");
}
}
});
udpReceiverThread.start();
}
/**
* Stop NIO receiver process thread.
* @return
*/
public void stopNIOUDPReceiverProcess()
{
isRunning = false;
udpReceiverThread = null;
}
/**
* Start NIO sender process thread.
* @param The port and the ip for connecting.
* @return
*/
public void startNIOUDPSenderProcess(final String connect_ip, final int connect_port)
{
udpSenderThread = new Thread(new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
mSenderPort = connect_port;
mSenderChannel = DatagramChannel.open( );
mSenderSocket = mSenderChannel.socket( );
mSenderAddress = new InetSocketAddress(connect_ip, connect_port);
mSenderChannel.socket( ).connect(mSenderAddress);
mSenderChannel.configureBlocking(false);
}
catch (SocketException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Open socket error.");
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Bind socket error.");
}
}
});
udpSenderThread.start();
}
/**
* The process of which channel is used to receiving.
* @param The buffer is for receiving. The selector for selecting the udp socket channel
* which is used to receiving.
* @return
*/
private void receiveProcess(ByteBuffer mReceiveBuffer, Selector mSelector)
{
try
{
mSelector.select();
Iterator mIterator = mSelector.selectedKeys().iterator();
while(mIterator.hasNext())
{
SelectionKey mClientKey = mIterator.next();
if(mClientKey.isReadable())
{
mChannel = (DatagramChannel) mClientKey.channel();
mReceiveBuffer.clear();
if (mChannel.receive(mReceiveBuffer) != null)
{
mReceiveBuffer.flip();
int mSize = mReceiveBuffer.limit();
byte[] mMessageBuffer = new byte[mSize];
mReceiveBuffer.get(mMessageBuffer);
String message = new String(mMessageBuffer);
decomposePacket(message);
mServerStatusListenerCallback.displayMessage(mRemote_IP+
"("+mRemote_Port+")"+
":"+mReceive_Message+
"\r\n");
}
}
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Receive process error.");
}
}
/**
* The process of which channel is used to sending.
* @param The buffer is for sending. The selector for selecting the udp socket channel
* which is used to sending.
* @return
*/
public void sendProcess(final String message)
{
if(mSenderChannel == null || mSenderSocket == null)
return;
if(mSenderSocket.isClosed())
return;
udpClientThread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
ByteBuffer mSendBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
mSendBuffer.put(makePacket(getWiFiIP(),""+mSenderPort,message).getBytes());
mSendBuffer.flip();
mSenderChannel.send(mSendBuffer, mSenderAddress);
mServerStatusListenerCallback.displayMessage("Me:"+message+"\r\n");
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("BK","Send process error.");
}
}
});
udpClientThread.start();
}
/**
* Make the special format packet including ip ,port and message.
* @param The ip address ,port ,message of sender.
* @return The composed packet.
*/
public String makePacket(String ip, String port, String message)
{
String section = "\r\n\r\n";
String return_Str = "ip:" + ip + section+
"port:" + port + section+
"message:" + message + section;
return return_Str;
}
/**
* Get the Wi-Fi ip address by using the WifiManager.
* @return The ip address of Wi-Fi.
*/
public String getWiFiIP()
{
WifiManager wm = (WifiManager) mContext.getSystemService( Context.WIFI_SERVICE);
WifiInfo wifiInf = wm.getConnectionInfo();
long ip = wifiInf.getIpAddress();
if( ip != 0 )
return String.format( "%d.%d.%d.%d",
(ip & 0xff),
(ip >> 8 & 0xff),
(ip >> 16 & 0xff),
(ip >> 24 & 0xff));
else
return "0.0.0.0";
}
/**
* Decompose the packet for getting remote ip ,remote port and remote message.
* @return
*/
public void decomposePacket(String receive_message)
{
String[] spilt_message = receive_message.split("\r\n\r\n");
mRemote_IP = spilt_message[0].substring(spilt_message[0].indexOf(":")+1,
spilt_message[0].length());
mRemote_Port = spilt_message[1].substring(spilt_message[1].indexOf(":")+1,
spilt_message[1].length());
mReceive_Message = spilt_message[2].substring(spilt_message[2].indexOf(":")+1,
spilt_message[2].length());
}
}
沒有留言 :
張貼留言