備註:輸入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>
沒有留言 :
張貼留言