[android]一个关于UDP和TCP的项目实践(二)

来源:互联网 发布:java中怎么定义数组 编辑:程序博客网 时间:2024/06/15 17:24
    在上一篇[android]一个关于UDP和TCP的项目实践(一)中已经交代了项目逻辑和基本知识点,这篇解释代码。
    首先需要加上如下权限:
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <uses-permission android:name="android.permission.INTERNET"/>    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    注意udp广播,和udp广播监听需要绑定同一个端口。
    测试机的版本为4.4。
    UI设计的很简单,三个功能按钮分别为发送广播、停止发送广播以及清除Textview里的内容。按钮下面的两个TextView分别显
示收到的udp请求和tcp请求以及发送的tcp请求信息,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:gravity="center_horizontal"        android:paddingTop="20dp"        >        <Button            android:id="@+id/start"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="start"            />        <Button            android:id="@+id/stop"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="60dp"            android:text="stop"            />        <Button            android:id="@+id/clean"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="60dp"            android:text="clean"            />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:gravity="center_horizontal"        android:layout_weight="1"        android:padding="20dp"        >        <TextView            android:id="@+id/send_information"            android:layout_marginTop="30dp"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="0.5"            android:text="send"            />        <TextView            android:id="@+id/receive_information"            android:layout_marginTop="30dp"            android:text="receive"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="0.5"            />    </LinearLayout></LinearLayout>
    MainActivity中开启两个线程,分别用来接收tcp连接和接收udp多播并发送tcp连接:
  /* 开一个线程接收tcp 连接*/        new tcpReceive(receive_label).start();    /* 开一个线程接收udp多播并发送tcp 连接*/        new udpReceiveAndtcpSend().start();

tcpRecieve的代码如下:
package com.example.cxlveu.udpreceiveandtcpsend;import android.util.Log;import android.widget.TextView;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;/** * Created by cxlveu on 16/4/8. *//* 接收tcp连接 */public class tcpReceive extends Thread{    private final static String TAG = "Tcp Receive";    private ServerSocket serverSocket;    private Socket socket;    private BufferedReader br;    private String source_address = "";    private TextView receive_label;    public tcpReceive(TextView textView){        this.receive_label = textView;    }    @Override    public void run(){        while (true){            serverSocket = null;            socket = null;            br = null;            try {                Log.i(TAG, " new ServerSocket start");                serverSocket = new ServerSocket(8080);                socket = serverSocket.accept();                Log.i(TAG," get socket");                if(socket != null){                    br = new BufferedReader(new InputStreamReader(socket.getInputStream()));                    StringBuilder sb = new StringBuilder();                    sb.append(socket.getInetAddress().getAddress());                    Log.i(TAG, sb.toString().trim());                    String line = null;                    while ((line = br.readLine()) != null){                        sb.append(line);                    }                    source_address = sb.toString().trim();receive_label.post(new Runnable() {                        @Override                        public void run() {                            receive_label.append("收到来自: " + "\n" + source_address + "\n" + "的tcp请求\n\n");                        }                    });                }            } catch (IOException e1) {                e1.printStackTrace();            } finally {                try {                    if (br != null)                        br.close();                    if (socket != null)                        socket.close();                    if (serverSocket != null)                        serverSocket.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}
    
udpReceiveAndtcpSend的代码如下:
private class udpReceiveAndtcpSend extends Thread{        @Override        public void run(){            // 设置缓冲区            byte[] data = new byte[1024];            try {                InetAddress groupAddress = InetAddress.getByName("224.0.0.1");                ms = new MulticastSocket(6789);                ms.joinGroup(groupAddress);            } catch (Exception e) {                e.printStackTrace();            }            while(true){                try {                    dp = new DatagramPacket(data, data.length);                    if (ms != null)                        ms.receive(dp);                } catch (Exception e) {                    e.printStackTrace();                }                if(dp.getAddress() != null){                    final String quest_ip = dp.getAddress().toString();                    final String codeString = new String(data, 0, dp.getLength());                    receive_label.post(new Runnable() {                        @Override                        public void run() {                            receive_label.append("收到来自: \n" + quest_ip.substring(1) + "\n" +"的udp请求\n");                            receive_label.append("请求内容: " + codeString + "\n\n");                        }                    });                    try {                        final String target_ip = dp.getAddress().toString().substring(1);                        send_label.post(new Runnable() {                            @Override                            public void run() {                                send_label.append("发送tcp请求到: \n" + target_ip + "\n");                            }                        });                        socket = new Socket(target_ip, 8080);                    } catch (IOException e) {                        e.printStackTrace();                    } finally {                        try {                            if (socket != null)                                socket.close();                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                }            }        }    }


在点击发送按钮时会执行udp的多播。注意的是在主线程中不能直接进行网络操作,因此需要开启新的线程。
  case R.id.start:                startBroadCast.setEnabled(false);                stopBroadCast.setEnabled(true);                /* 新开一个线程发送udp多播 */                new udpBroadCast("hello!").start();                break;


udpBroadCast的代码如下:
private  class udpBroadCast extends Thread {        MulticastSocket sender = null;        DatagramPacket dp = null;        InetAddress group = null;        byte[] data = new byte[1024];        public udpBroadCast(String dataString) {            data = dataString.getBytes();        }        @Override        public void run() {            try {                sender = new MulticastSocket();                group = InetAddress.getByName("224.0.0.1");                dp = new DatagramPacket(data,data.length,group,6789);                sender.send(dp);                sender.close();            } catch(IOException e) {                e.printStackTrace();            }        }    }

要注意端口的一致性。
    以上就是整个项目的主要代码。功能比较基础,还是需要结合实际的开发做修改。
    完整代码请参考:项目代码
    
0 0
原创粉丝点击