关闭

Android使用Socket(Tcp/Udp)协议进行数据传输(传输大文件)

标签: androidsocket网络编程
636人阅读 评论(0) 收藏 举报
分类:

Socket是什么:所谓Socket 通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。Socket内部又有两种协议(Tcp/Udp),我们来说说其各自的特点。

先来说说网络编程的三要素

1.IP地址:网络中计算机的唯一标识
2.端口
3.协议:通信的规则

Tcp/Udp特点

一、 TCP(协议):

  • 建立连接,形成传输数据的通道
  • 在连接中进行大数据量传输
  • 通过三次握手完成连接,是可靠协议
  • 必须建立连接,效率稍微低点

二. UDP(协议):

  • 将数据及源和目的封装在数据包中,不需要建立连接
  • 每个数据包的大小限制在64K内
  • 因无连接,是不可靠协议
  • 不需要建立连接,速度快

Socket工作图解

Socket图解

TCP协议进行数据传输,实现两台设备的一个简单数据发送。

客户端发送数据

     /**
     * @param serverAddress 要发送到服务端的ip
     * 1.创建socket并指定ip和端口号
     * 2.获取输出流,写数据 
     * 3.释放资源
     * 4.Tcp一定要先开接收端
     */
    public void send_tcp(String serverAddress) {
        try {
            Socket s = new Socket(serverAddress, WIFIAdmin.PORT);
            //为了发送数据,应该获得socket流中的输出流
            OutputStream out = s.getOutputStream();
            out.write((content.getText().toString()).getBytes());
            s.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端接收数据

    /**
     * TCP协议接收数据 
     * 1.创建接收端的Socket对象 
     * 2.监听客户端接收,返回一个Socket对象
     * 3.获取输入流,读取数据显示在控制台
     * 4.释放资源
     */
    public void receive_tcp() {
            try {
                //1.建立连接,监听端口
                ServerSocket ss = new ServerSocket(WIFIAdmin.PORT);
                //2.连接客户端对象
                while (true) {
                //阻塞式方法,只有客户端连接了才会继续往下运行
                    Socket accept = ss.accept();
                    //获取ip
                    String ip = accept.getInetAddress().getHostAddress();
                    //3.获取客户端发送过来的数据
                    InputStream in = accept.getInputStream();
                    //4.开始读取,获取输入信息
                    BufferedReader bff = new BufferedReader(new InputStreamReader(in));
                    //读取信息
                    String line;
                    final StringBuilder sb = new StringBuilder();
                    while ((line = bff.readLine()) != null) {
                        sb.append(line);
                    }
                    Message message = new Message();
                    message.obj = sb.toString();
                    handler.sendMessage(message);
                    //5.关闭
                    //ss.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

现在来看下UDP协议是怎么进行数据传输的。

先来看下发送端

    /*
     * UDP协议发送数据:
     * 1.创建发送端Socket对象
     * 2.创建数据,并把数据打包
     * 3.调用Socket对象发送方法发送数据包
     * 4.释放资源
     */
    private void udpSendMessage() {
        DhcpInfo info = wifiManager.getDhcpInfo();
        String serverAddress = WIFIAdmin.intToIp(info.serverAddress);
        // 创建发送端Socket对象
        try {
            // 创建发送端Socket对象
            DatagramSocket ds = new DatagramSocket();
            // 创建数据,并把数据打包
            byte[] bys = content.getText().toString().getBytes();
            DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName(serverAddress),
                    WIFIAdmin.UDP_PORT);
            // 调用Socket对象发送方法发送数据包
            ds.send(dp);
            // 释放资源
            ds.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

在瞄一下接收端

    /*
     * UDP协议接收数据:
     * 1.创建接收端Socket对象
     * 2.创建一个数据包(接收容器)
     * 3.调用Socket对象接收方法接收数据包
     * 4.解析数据包
     * 5.释放资源
     */
    private void receive_udp() {
        try {
            // 创建接收端Socket对象
            DatagramSocket ds = new DatagramSocket(WIFIAdmin.UDP_PORT);
            // 创建一个数据包(接收容器)
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);
            // 调用Socket对象接收方法接收数据包
            ds.receive(dp);
            // 获取对方的ip
            String ip = dp.getAddress().getHostAddress();
            // 解析数据
            String data = new String(dp.getData(), 0, dp.getLength());
            Message message = new Message();
            message.obj = data;
            message.what = 2;
            handler.sendMessage(message);
            ds.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用Tcp协议传输大文件,循环将数据写入流中(Tcp发送端)

    /*
     * @param path     文件路径
     * @param FileName 文件名
     */
public void sendFile(String path, String FileName) {
            DhcpInfo info = wifiManager.getDhcpInfo();
            serverAddress = WifiAdmin.intToIp(info.serverAddress);  
            Socket s = new Socket(serverAddress, PORT);
            OutputStream out = s.getOutputStream();
            //将文件名写在流的头部以#分割
            out.write((FileName + "#").getBytes());
            FileInputStream inputStream = new FileInputStream(new File(path));
            byte[] buf = new byte[1024];
            int len;
            //判断是否读到文件末尾
            while ((len = inputStream.read(buf)) != -1) {
                out.write(buf, 0, len);//将文件循环写入输出流
            }
            //告诉服务端,文件已传输完毕
            s.shutdownOutput();
            //获取从服务端反馈的信息
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String serverBack = in.readLine();
            Log.d("TAG", serverBack);
            //资源关闭
            s.close();
            inputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

大文件传输(Tcp接收端)

public synchronized void receiveFile() {
        try {
            ServerSocket ss = new ServerSocket(WifiAdmin.PORT);
            while (true) {
                Socket socket = ss.accept();
                InputStream in = socket.getInputStream();
            int content;
            //装载文件名的数组
            byte[] c = new byte[1024];
            //解析流中的文件名,也就是开头的流
            for (int i = 0; (content = in.read()) != -1; i++) {
                //表示文件名已经读取完毕
                if (content == '#') {
                    break;
                }
                c[i] = (byte) content;
            }
            //将byte[]转化为字符,也就是我们需要的文件名
            String FileName = new String(c, "utf-8").trim();
                //创建一个文件,指定保存路径和刚才传输过来的文件名
                OutputStream saveFile = new FileOutputStream(
                        new File(Environment.getExternalStorageDirectory().toString(), FileName));
                byte[] buf = new byte[1024];
                int len;
                //判断是否读到文件末尾
                while ((len = in.read(buf)) != -1) {
                    saveFile.write(buf, 0, len);
                }
                saveFile.flush();
                saveFile.close();
                //告诉发送端我已经接收完毕
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("文件接收成功".getBytes());
                outputStream.flush();
                outputStream.close();
                socket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

掌握了Socket的基本传输规则,相信你很快就能写出一个利用局域网让两台设备进行数据传输了。

最后附上Demo下载地址

3
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:80519次
    • 积分:1768
    • 等级:
    • 排名:千里之外
    • 原创:72篇
    • 转载:1篇
    • 译文:0篇
    • 评论:130条
    轻松一刻
    友情链接
    最新评论