備註:輸入IP與Port後啟動Client,發送任意訊息後,Client會收到Server的回覆
MainActivity.java
import java.io.IOException;
import java.net.InetSocketAddress;
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.Iterator;
import android.os.Bundle;
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;
import android.app.Activity;
public class MainActivity extends Activity implements OnClickListener
{
private TextView tvDisplay;
private EditText etPort,etIP,etMessage;
private Button btStartOrClose,btSend;
private boolean isRunning = false;
private DatagramChannel mClientChannel;
private Selector mSelector;
private int MAX_PACKET_SIZE = 1024;
private InetSocketAddress mRemoteAddress;
private int port = 0;
private String ip = "0.0.0.0";
private String send_message = "";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initial UI component
tvDisplay = (TextView) findViewById(R.id.xml_tvDisplay);
etPort = (EditText) findViewById(R.id.xml_etPort);
etIP = (EditText) findViewById(R.id.xml_etIP);
etMessage = (EditText) findViewById(R.id.xml_etMessage);
btStartOrClose = (Button) findViewById(R.id.xml_btStartOrClose);
btSend = (Button) findViewById(R.id.xml_btSend);
btSend.setOnClickListener(this);
btStartOrClose.setOnClickListener(this);
//
}
@Override
protected void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
//stop udp client process
isRunning = false;
//
}
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
switch(v.getId())
{
case R.id.xml_btStartOrClose:
if(etIP.getText().length() != 0 && etPort.getText().length() != 0)
{
if(!isRunning)
{
btStartOrClose.setText("Close");
ip = etIP.getText().toString();
port = Integer.valueOf(etPort.getText().toString());
isRunning = true;
new Thread(startUDPClientProcess).start();
}
else
{
btStartOrClose.setText("Start");
//stop udp client process
isRunning = false;
//
}
}
break;
case R.id.xml_btSend:
if(etMessage.getText().length() != 0)
{
send_message = etMessage.getText().toString();
if(mRemoteAddress==null)
return;
new Thread(sendMessageProcess).start();
}
break;
default:
break;
}
}
//start udp client process
private Runnable startUDPClientProcess = new Runnable()
{
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
mRemoteAddress = new InetSocketAddress(ip,port);
try
{
mSelector = Selector.open();
mClientChannel = DatagramChannel.open();
mClientChannel.configureBlocking(false);
mClientChannel.connect(mRemoteAddress);
}
catch(IOException e)
{
e.printStackTrace();
Log.e("NIOUDP_Client","Selector opening or channel opening fail.");
}
mClientChannel.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();
int len = mChannel.read(mReceiveBuffer);
if (len != 0)
{
mReceiveBuffer.flip();
int mSize = mReceiveBuffer.limit();
byte[] mMessageBuffer = new byte[mSize];
mReceiveBuffer.get(mMessageBuffer);
final String message = mRemoteAddress+":\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);
}
});
//
}
}
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_Client","The selector selects fail.");
}
}
//close channel and selector
try
{
mClientChannel.keyFor(mSelector).cancel();
mClientChannel.disconnect();
mClientChannel.socket().close();
mClientChannel.close();
mSelector.close();
mSelector = null;
mClientChannel = null;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("NIOUDP_Client","Close channel fail.");
}
//
}
catch(ClosedChannelException c)
{
c.printStackTrace();
Log.e("NIOUDP_Client","Channel registering fail.");
isRunning = false;
return;
}
//
}
};
//
//send the message
private Runnable sendMessageProcess = new Runnable()
{
@Override
public void run()
{
try
{
ByteBuffer mSendBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE);
mSendBuffer.put(send_message.getBytes());
mSendBuffer.flip();
int size = mClientChannel.send(mSendBuffer, mRemoteAddress);
if(size == 0)
{
mClientChannel.keyFor(mSelector).interestOps( mClientChannel.keyFor(mSelector).interestOps() ^ SelectionKey.OP_WRITE);
Log.e("NIOUDP_Client","ByteBuffer is full.");
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("NIOUDP_Client","Channel is already closed.");
}
}
};
//
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/xml"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<EditText
android:id="@+id/xml_etIP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/xml_btStartOrClose"
android:ems="10"
android:inputType="text" />
<TextView
android:id="@+id/xml_tvIP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/xml_etIP"
android:layout_alignParentLeft="true"
android:text="IP:"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/xml_btStartOrClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Start" />
<TextView
android:id="@+id/xml_tvPort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/xml_btStartOrClose"
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_alignBottom="@+id/xml_tvPort"
android:layout_alignRight="@+id/xml_etIP"
android:layout_toRightOf="@+id/xml_tvPort"
android:ems="10"
android:inputType="number"
android:minEms="5" >
<requestFocus />
</EditText>
<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_centerVertical="true"
android:lines="8"
android:maxLines="8"
android:text="Waiting for connecting..."
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/xml_etMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/xml_btStartOrClose"
android:ems="10"
android:inputType="textMultiLine" />
<Button
android:id="@+id/xml_btSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Send" />
</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>




沒有留言 :
張貼留言