羊皮書APP(Android版)開發(fā)系列(十二)Android Socket UDP大文件傳輸

Tcp和IP協(xié)議是很重要的內(nèi)容华坦,但是要理解這些協(xié)議最好的方式就是自己根據(jù)業(yè)務(wù)寫一些demo抠藕,加深理解粱腻。

業(yè)務(wù)需求是:通過(guò)電腦端(網(wǎng)頁(yè)或客戶端形式)發(fā)送文件到Android的客戶端燎含,下面是使用UDP實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的文件傳輸Demo,因UDP為不可靠傳輸帕翻,可能會(huì)丟包。

  • 服務(wù)器端發(fā)送本地文件萝风,代碼如下:
package client;

import server.udp.UDPUtils;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class UDPClient {

    private static final String SEND_FILE_PATH = "/Users/wangjie/Documents/123.mp4";

    public static void main(String[] args){
        long startTime = System.currentTimeMillis();

        byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
        byte[] receiveBuf = new byte[1];

        RandomAccessFile accessFile = null;
        DatagramPacket dpk = null;
        DatagramSocket dsk = null;
        int readSize = -1;
        try {
            accessFile = new RandomAccessFile(SEND_FILE_PATH,"r");
//            dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("localhost"), UDPUtils.PORT + 1));
            dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("192.168.1.119"), UDPUtils.PORT + 1));
            dsk = new DatagramSocket(UDPUtils.PORT);
            int sendCount = 0;
            while((readSize = accessFile.read(buf,0,buf.length)) != -1){
                System.out.println("readSize:"+readSize);
                dpk.setData(buf, 0, readSize);
                dsk.send(dpk);
                // wait server response
                {
                    while(true){
                        dpk.setData(receiveBuf, 0, receiveBuf.length);
                        dsk.receive(dpk);

                        // confirm server receive
                        if(!UDPUtils.isEqualsByteArray(UDPUtils.successData,receiveBuf,dpk.getLength())){
                            System.out.println("resend ...");
                            dpk.setData(buf, 0, readSize);
                            dsk.send(dpk);
                        }else
                            break;
                    }
                }

                System.out.println("send count of "+(++sendCount)+"!");
            }
            // send exit wait server response
            while(true){
                System.out.println("client send exit message ....");
                dpk.setData(UDPUtils.exitData,0,UDPUtils.exitData.length);
                dsk.send(dpk);

                dpk.setData(receiveBuf,0,receiveBuf.length);
                dsk.receive(dpk);
                // byte[] receiveData = dpk.getData();
                if(!UDPUtils.isEqualsByteArray(UDPUtils.exitData, receiveBuf, dpk.getLength())){
                    System.out.println("client Resend exit message ....");
                    dsk.send(dpk);
                }else
                    break;
            }
        }catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                if(accessFile != null)
                    accessFile.close();
                if(dsk != null)
                    dsk.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        long endTime = System.currentTimeMillis();
        System.out.println("time:"+(endTime - startTime));
    }
}
  • 客戶端接收文件存到本地嘀掸,代碼如下:
package cn.studyou.androidsocket;


import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class UDPReceiveFileActivity extends Activity {

    private String localUrl;
    private static final String FILE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/VideoCache/";
    private static final String SAVE_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/VideoCache/";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_udpfile_mplayer);

        Log.e("FILE_DIR", FILE_DIR);
        new Thread(new Runnable() {
            @Override
            public void run() {
                receiveFile();
            }
        }).start();
    }
    public void receiveFile() {

        byte[] buf = new byte[UDPUtils.BUFFER_SIZE];

        DatagramPacket dpk = null;
        DatagramSocket dsk = null;
        BufferedOutputStream bos = null;
        try {
            InetAddress loc = InetAddress.getByName("192.168.1.107");

            dpk = new DatagramPacket(buf, buf.length, new InetSocketAddress(loc, UDPUtils.PORT));
            dsk = new DatagramSocket(UDPUtils.PORT + 1);

            if (localUrl == null) {
                localUrl = SAVE_FILE_PATH + "1235.mp4";
            }
            File cacheFile = new File(localUrl);

            if (!cacheFile.exists()) {
                cacheFile.getParentFile().mkdirs();
                cacheFile.createNewFile();
            }
            bos = new BufferedOutputStream(new FileOutputStream(localUrl));
            System.out.println("wait client ....");
            dsk.receive(dpk);
            System.out.println("wait clientq ....");

            int readSize = 0;
            int readCount = 0;
            int flushSize = 0;
            while ((readSize = dpk.getLength()) != 0) {
                // validate client send exit flag
                if (UDPUtils.isEqualsByteArray(UDPUtils.exitData, buf, readSize)) {
                    System.out.println("server exit ...");
                    // send exit flag
                    dpk.setData(UDPUtils.exitData, 0, UDPUtils.exitData.length);
                    dsk.send(dpk);
                    break;
                }

                bos.write(buf, 0, readSize);
                if (++flushSize % 1000 == 0) {
                    flushSize = 0;
                    bos.flush();
                }
                dpk.setData(UDPUtils.successData, 0, UDPUtils.successData.length);
                dsk.send(dpk);

                dpk.setData(buf, 0, buf.length);
                System.out.println("receive count of " + (++readCount) + " !");
                dsk.receive(dpk);
            }

            // last flush
            bos.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bos != null)
                    bos.close();
                if (dsk != null)
                    dsk.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市规惰,隨后出現(xiàn)的幾起案子睬塌,更是在濱河造成了極大的恐慌,老刑警劉巖歇万,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揩晴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贪磺,警方通過(guò)查閱死者的電腦和手機(jī)硫兰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寒锚,“玉大人劫映,你說(shuō)我怎么就攤上這事违孝。” “怎么了苏研?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵等浊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我摹蘑,道長(zhǎng)筹燕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任衅鹿,我火速辦了婚禮撒踪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘大渤。我一直安慰自己制妄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布泵三。 她就那樣靜靜地躺著耕捞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烫幕。 梳的紋絲不亂的頭發(fā)上俺抽,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音较曼,去河邊找鬼磷斧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛捷犹,可吹牛的內(nèi)容都是我干的弛饭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼萍歉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼侣颂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起翠桦,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤横蜒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后销凑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丛晌,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年斗幼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澎蛛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜕窿,死狀恐怖谋逻,靈堂內(nèi)的尸體忽然破棺而出呆馁,到底是詐尸還是另有隱情,我是刑警寧澤毁兆,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布浙滤,位于F島的核電站,受9級(jí)特大地震影響气堕,放射性物質(zhì)發(fā)生泄漏纺腊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一茎芭、第九天 我趴在偏房一處隱蔽的房頂上張望揖膜。 院中可真熱鬧,春花似錦梅桩、人聲如沸壹粟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)趁仙。三九已至,卻和暖如春垦页,著一層夾襖步出監(jiān)牢的瞬間幸撕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工外臂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人律胀。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓宋光,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親炭菌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子罪佳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,302評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)黑低,斷路器赘艳,智...
    卡卡羅2017閱讀 134,704評(píng)論 18 139
  • 有一句話說(shuō),“歲月且淺克握,來(lái)年蕾管,你會(huì)發(fā)現(xiàn)現(xiàn)在過(guò)不去的,不過(guò)如此”菩暗。 很小的時(shí)候掰曾,喜愛的洋娃娃被送給了其...
    墨紫七閱讀 342評(píng)論 0 0
  • 1. 入門 Sanic 是一款類似Flask的Web服務(wù)器,它運(yùn)行在Python 3.5+上停团。 除了與Flask功...
    JasonJe閱讀 13,922評(píng)論 4 37
  • 和張小潔從招聘會(huì)落荒而逃旷坦。曾經(jīng)想過(guò)的大四掏熬,是飄逸的長(zhǎng)發(fā)和黑色薄紗質(zhì)地的包臀連衣裙,近10厘米高的高跟鞋可以讓整...
    她比四月還燦爛閱讀 191評(píng)論 0 0