編輯:關於Android編程
之前寫過一些關於TCP和UDP數據傳輸的代碼,比如使用TCP傳輸音視頻數據包,P2P打洞中使用UDP等。寫好之後就直接丟下了,沒有總結下都。最近准備找工作,再拿來溫習下。
暫時把自己的定位很明確,就是android應用層的開發,所以關於TCP/UDP的實現細節,暫時也不想去深究。但是心裡清楚這個必須去看的,有時間推薦大家看看《TCP/IP詳解》,或者網上有很多大牛的總結。
new Socket(ip, prot);我們可以通過上面的方式創建一個socket,如果失敗,會拋出IOException。參數中的IP和Port是目標服務器的IP和端口號。若你想得到本地的IP和端口可通過這個socket拿到。當然,創建socket還有多種構造方法,比如 new Socket(proxy) ,如果有需要你可以查閱相關說明。
InputStream is = mSocket.getInputStream(); OutputStream out = mSocket.getOutputStream();通過輸出流,我們可以使用is.read(receiveBuffer)和out.write(data);來進行數據的收發。這裡給兩個簡單實例:
@Override public void execute() { try { int count = is.read(receiveBuffer); if (count == -1) { notifyError(); } byte[] data = getPacket(receiveBuffer, count, is); mReceiverQueue.put(data); } catch (InterruptedException e) { e.printStackTrace(); notifyError(); } catch (IOException e) { e.printStackTrace(); notifyError(); } }假如我們的數據包協議格式如下:
@Override public void execute() { try { byte[] data = mSenderQueue.take(); out.write(data); } catch (InterruptedException e) { e.printStackTrace(); notifyError(); } catch (IOException e) { e.printStackTrace(); notifyError(); } }mSenderQueue和mReceiverQueue一樣,都是阻塞隊列。發送的時候,我們從隊列中取出要發送的數據,然後通過輸出流寫入即可。這個地方比發送簡單了一些。可能你已經注意到,我的發送和接收都用了阻塞隊列,這個原因就是考慮到大量數據的時候做一個緩沖,如果沒有緩沖,可能導致代碼的阻塞。另外就是當我們的阻塞隊列充滿的時候可以手動丟棄一些數據,這個就是具體應用了。
try { ServerSocket serverSocket = new ServerSocket(9559); while (true) { Socket socket = serverSocket.accept(); // new ServiceSocketThread(socket).start(); } } catch (Exception e) { e.printStackTrace(); }因為服務端不可能只與一個客戶端連接,因此上面的代碼寫在一個死循環中。拿到socket之後起一個新的線程來處理這個socket。
這個東西用的很少,就是當初測試P2P的時候用過。能想到的問題就是數據大小的問題,比如發送數據我們的數據定義為多大合適。但是最後沒有實際的項目驗證,在此也不好回答。先貼一段代碼出來:
public class UDPServer extends BaseThread { /** 發送隊列大小 */ public static final int SENDQUEUESIZE = 10; /** 接收隊列大小 */ public static final int RECEIVEQUEUESIZE = 10; /** TCP接收緩存大小 */ public static final int RECEIVERBUFFERSIZE = 1024; /** UDP接收緩存大小 */ public static final int RECEIVERPACKETSIZE = 1024 * 64; private int count = 0; private DatagramPacket receivePacket; private DatagramSocket mSocket; @Override public boolean prepare() { receivePacket = new DatagramPacket(new byte[RECEIVERPACKETSIZE], RECEIVERPACKETSIZE); try { mSocket = new DatagramSocket(9559); } catch (SocketException e) { System.out.println(String.format("udp connect init error: %s", e.getMessage())); return false; } return true; } @Override public void execute() { try { mSocket.receive(receivePacket); byte[] data = receivePacket.getData(); int length = receivePacket.getLength(); int offset = receivePacket.getOffset(); System.out.print(++count + String.format("length:%d|%d, offset:%d, data: %s \n", length, data.length, offset, new String(data, "gbk"))); System.out.println(data[1024]); } catch (SocketException e) { System.out.println(String.format("udp connect init error: %s", e.getMessage())); } catch (IOException e) { System.out.println(String.format("udp connect init error: %s", e.getMessage())); } } }byte[] data = receivePacket.getData();這個地方拿到的data是緩沖區的大小,他們地址是樣的,這個大家可以試試就知道。至於這個data中有多少數據,就需要我們通過receivePacket.getLength();拿到。
那麼我們就來用Handler制作一個簡易的網絡請求框架。如下圖:解釋一下:UI在request的時候傳入UI中的Handler,同時將請求的Runnable推入到工作線程
效果圖效果圖中我們實現了一個簡單的隨手指滑動的二階貝塞爾曲線,還有一個復雜點的,穿越所有已知點的貝塞爾曲線。學會使用貝塞爾曲線後可以實現例如QQ紅點滑動刪除啦,360動態
本節引言: 本節我們來把剩下的四種Drawable也學完,他們分別是: LayerDrawable,TransitionDrawable,Leve
Android 自定義輸入支付密碼的軟鍵盤 &nbs