備註:選定Port後啟動Server等待Client發送,收到Client訊息後,Server會回覆給Client
Non-Blocking UDP Server範例如下:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.http.conn.util.InetAddressUtils;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener
{
private TextView tvDisplay,tvLocalIP;
private EditText etPort;
private Button btStartOrClose;
private boolean isRunning = false;
private DatagramChannel mServerChannel;
private Selector mSelector;
private int MAX_PACKET_SIZE = 1024;
private int port = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initial UI component
tvDisplay = (TextView) findViewById(R.id.xml_tvDisplay);
tvLocalIP = (TextView) findViewById(R.id.xml_tvIP);
etPort = (EditText) findViewById(R.id.xml_etPort);
btStartOrClose = (Button) findViewById(R.id.xml_btStart);
btStartOrClose.setOnClickListener(this);
//get IP address and display it
String LocalIPAddress = "";
try
{
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface intf : interfaces)
{
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
for (InetAddress addr : addrs)
{
if (!addr.isLoopbackAddress())
{
String sAddr = addr.getHostAddress().toUpperCase();
boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
if(isIPv4)
LocalIPAddress = sAddr;
else
{
int delim = sAddr.indexOf('%'); // drop ip6 port suffix
LocalIPAddress = delim<0 ? sAddr : sAddr.substring(0, delim);
}
}
}
}
}
catch(SocketException e)
{
Log.e("NIOUDP_Server","Get network informaton fail.");
}
if(LocalIPAddress != "")
tvLocalIP.setText(LocalIPAddress);
//
}
@Override
protected void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
//stop udp server process
isRunning = false;
//
}
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
switch(v.getId())
{
case R.id.xml_btStart:
if(etPort.getText().length() != 0 && etPort.getText().toString() != null)
{
if(!isRunning)
{
btStartOrClose.setText("Close");
port = Integer.valueOf(etPort.getText().toString());
isRunning = true;
new Thread(startUDPServerProcess).start();
}
else
{
btStartOrClose.setText("Start");
//stop udp server process
isRunning = false;
//
}
}
break;
default:
break;
}
}
//start udp server process
private Runnable startUDPServerProcess = new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
//open the channel and the selector
try
{
mSelector = Selector.open();
mServerChannel = DatagramChannel.open();
mServerChannel.configureBlocking(false);
}
catch(IOException e)
{
e.printStackTrace();
Log.e("NIOUDP_Server","Selector opening or channel opening fail.");
}
//
//start server to bind the port and register channel to listen reading or writing event
mServerChannel.socket().setReuseAddress(true);
mServerChannel.socket().bind(new InetSocketAddress(port));
mServerChannel.register(mSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//
//the selector select the channel event and receive message
ByteBuffer mReceiveBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
while(isRunning)
{
try
{
mSelector.select();
Iterator<SelectionKey> mIterator = mSelector.selectedKeys().iterator();
while(mIterator.hasNext())
{
SelectionKey mKey = mIterator.next();
if(mKey.isReadable())
{
mReceiveBuffer.clear();
DatagramChannel mChannel = (DatagramChannel) mKey.channel();
SocketAddress mAddress = mChannel.receive(mReceiveBuffer);
if (mAddress != null)
{
mReceiveBuffer.flip();
int mSize = mReceiveBuffer.limit();
byte[] mMessageBuffer = new byte[mSize];
mReceiveBuffer.get(mMessageBuffer);
final String message = mAddress+":\r\n"+new String(mMessageBuffer);
//display the message which is received
runOnUiThread(new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
String displayMessage = tvDisplay.getText().toString();
if(displayMessage.contains("Waiting")|| tvDisplay.getLineCount() > 6)
tvDisplay.setText("");
displayMessage = tvDisplay.getText().toString()+"\r\n"+message;
tvDisplay.setText(displayMessage);
}
});
//
//send the request message
try
{
String sendMessage = "OK!!I have got your message!!";
ByteBuffer mSendBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
mSendBuffer.put(sendMessage.getBytes());
mSendBuffer.flip();
int size = mServerChannel.send(mSendBuffer, mAddress);
if(size == 0)
{
mKey.interestOps(mKey.interestOps() ^ SelectionKey.OP_WRITE);
Log.e("NIOUDP_Server","ByteBuffer is full.");
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("NIOUDP_Server","Channel is already closed.");
}
//
}
}
else if(mKey.isWritable())
{
mKey.interestOps(mKey.interestOps() ^ SelectionKey.OP_WRITE);
}
}
mIterator.remove();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("NIOUDP_Server","The selector selects fail.");
}
}
//
//close channel and selector
try
{
mSelector.close();
mServerChannel.close();
mSelector = null;
mServerChannel = null;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("NIOUDP_Server","Close socket fail.");
}
//
}
catch (SocketException s)
{
// TODO Auto-generated catch block
s.printStackTrace();
Log.e("NIOUDP_Server","Socket binding fail.");
isRunning = false;
return;
}
catch(ClosedChannelException c)
{
c.printStackTrace();
Log.e("NIOUDP_Server","Channel registering fail.");
isRunning = false;
return;
}
}
};
//
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/xml_etStart"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="@+id/xml_tvDisplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:lines="8"
android:maxLines="8"
android:text="Waiting for connecting..."
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/xml_btStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/xml_tvDisplay"
android:text="Start" />
<TextView
android:id="@+id/xml_tvPort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/xml_etPort"
android:layout_alignBottom="@+id/xml_etPort"
android:layout_alignParentLeft="true"
android:text="Port:"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/xml_etPort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/xml_btStart"
android:layout_alignBottom="@+id/xml_btStart"
android:layout_toLeftOf="@+id/xml_btStart"
android:layout_toRightOf="@+id/xml_tvPort"
android:ems="10"
android:inputType="number" />
<TextView
android:id="@+id/xml_tvLocalIP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/xml_btStart"
android:text="Local IP: "
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/xml_tvIP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/xml_btStart"
android:layout_toRightOf="@+id/xml_tvLocalIP"
android:text="0.0.0.0"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nio_udpclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.nio_udpclient.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>


沒有留言 :
張貼留言