【Android Socket专题】: UDP通信服务器端app的demo的实现

Android Socket 专题:

 

UDP Client客户端  http://blog.csdn.net/shankezh/article/details/50731287

UDP Server服务器 http://blog.csdn.net/shankezh/article/details/51452811

TCP Client客户端  http://blog.csdn.net/shankezh/article/details/70763579

TCP Server服务器 http://blog.csdn.net/shankezh/article/details/51555455

 

这个章节补充UDP Server服务器的内容。

首先规划自己的界面,附上XML效果图:

附上Xml代码:

 

<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:layout_weight="2"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="2">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="ip:"/>
            <EditText
                android:layout_width="0dp"
                android:layout_weight="2"
                android:layout_height="match_parent"
                android:id="@+id/editIp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="port"/>
            <EditText
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:id="@+id/editPort"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1">

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:id="@+id/btn_udpStart"
                android:text="开启服务器" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:id="@+id/btn_udpClose"
                android:text="关闭连接" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"

                android:id="@+id/btn_CleanRcv"
                android:text="清除接收区" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:id="@+id/btn_CleanSend"
                android:text="清除接收区" />
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="bottom"
            android:text="接收区:" />
        <TextView
            android:layout_width="match_parent"
            android:layout_weight="7"
            android:layout_height="0dp"
            android:id="@+id/txt_Rcv"
            android:background="@android:color/holo_blue_light"
            />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="发送区:" />
        <TextView
            android:layout_width="match_parent"
            android:layout_weight="7"
            android:background="@android:color/holo_purple"
            android:id="@+id/txt_Send"
            android:layout_height="0dp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="2">
            <EditText
                android:layout_width="0dp"
                android:layout_weight="5"
                android:id="@+id/edit_Send"
                android:layout_height="match_parent" />
            <Button
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:layout_gravity="right"
                android:id="@+id/btn_Send"
                android:text="发送"/>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>


界面布局完成,讲一点关键性的东西。

 

与UDP客户端一样的是,实现UDP服务器关键在于这几个类:

1、DatagramSocket

2、DatagramPacket

3、InetSocketAddress

需要各位自己搜索一下这几个类的意思,我就偷个懒。

 

Udp Server服务器的收发与UDP Client客户端如出一辙,实现思路如下:

 

1、创建DatagramSocket通信数据报

2、建立接收事件专用DatagramPacket数据包

3、创建超时(这个和后面关闭通信有关)

4、建立监听接收消息循环机制(接收消息处理在此处,接收到的消息通过BroadcastReceiver发送给主界面)

5、结束循环,关闭数据报。

 

Udp Server 服务器发送消息的函数实现思路如下:

 

1、共享一个DatagramSocket

2、从接收数据包那儿获取对方的ip和port

3、更新需要发送的内容到DatagramPacket

4、使用之前的DatagramSocket的发送方法将内容发出去

调用的时候直接在新线程里调用这个函数方法即可。

 

具体看代码实现:

 

package com.example.udpserver;

import android.content.Intent;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
 * Created by Jason on 2016/5/18.
 */
public class UdpServer implements Runnable {
    private String ip = null;
    private int port = 0;
    private DatagramPacket dpRcv = null,dpSend = null;
    private static DatagramSocket ds = null;
    private InetSocketAddress inetSocketAddress = null;
    private byte[] msgRcv = new byte[1024];
    private boolean udpLife = true;     //udp生命线程
    private boolean udpLifeOver = true; //生命结束标志,false为结束


    public UdpServer(String mIp, int mPort) {
        this.ip = mIp;
        this.port = mPort;
    }

    private void SetSoTime(int ms) throws SocketException {
        ds.setSoTimeout(ms);
    }

    //返回udp生命线程因子是否存活
    public boolean isUdpLife(){
        if (udpLife){
            return true;
        }

        return false;
    }

    //返回具体线程生命信息是否完结
    public boolean getLifeMsg(){
        return udpLifeOver;
    }

    //更改UDP生命线程因子
    public void setUdpLife(boolean b){
        udpLife = b;
    }

    public void Send(String sendStr) throws IOException {
        Log.i("SocketInfo","客户端IP:"+ dpRcv.getAddress().getHostAddress() +"客户端Port:"+ dpRcv.getPort());
        dpSend = new DatagramPacket(sendStr.getBytes(),sendStr.getBytes().length,dpRcv.getAddress(),dpRcv.getPort());
        ds.send(dpSend);
    }


    @Override
    public void run() {
        inetSocketAddress = new InetSocketAddress(ip, port);
        try {
            ds = new DatagramSocket(inetSocketAddress);
            Log.i("SocketInfo", "UDP服务器已经启动");

            SetSoTime(3000);
            //设置超时,不需要可以删除
        } catch (SocketException e) {
            e.printStackTrace();
        }

        dpRcv = new DatagramPacket(msgRcv, msgRcv.length);
        while (udpLife) {
            try {
                Log.i("SocketInfo", "UDP监听中");
                ds.receive(dpRcv);

                String string = new String(dpRcv.getData(), dpRcv.getOffset(), dpRcv.getLength());
                Log.i("SocketInfo", "收到信息:" + string);
                Intent intent =new Intent();
                intent.setAction("udpReceiver");
                intent.putExtra("udpReceiver",string);
                MainActivity.context.sendBroadcast(intent);//将消息发送给主界面

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

        }
        ds.close();
        Log.i("SocketInfo","UDP监听关闭");
        //udp生命结束
        udpLifeOver = false;
    }
}


至此,核心代码部署完成,期间关于发送给主界面的,设置超时,不需要的可以删除。

 

 

下面主界面代码实现:

 

 

MyHandler类(主要处理UI更新事件)

 

OnCreate(绑定控件,事件监听,注册BroadcastReceiver等)

 

MyBtnClick类(处理各按钮事件)

 

 

MyBroadcastReceiver(广播接收器)

 

看具体代码:

 

package com.example.udpserver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.io.IOException;
import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {
    private Button btnUdpStart, btnUdpClose,btnRcvClear,btnSendClear,btnUdpSend;
    private TextView txtRcv,txtSend;
    private EditText editSend,editIp,editPort;

    public static Context context ;

    private MyHandler myHandler =   new MyHandler(this);
    private MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    private MyBtnClick myBtnClick = new MyBtnClick();
    private static UdpServer udpServer = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        BindWidget();
        Listening();
        BindReceiver();
    }

    private void BindWidget(){
        btnUdpClose = (Button) findViewById(R.id.btn_udpClose);
        btnUdpStart = (Button) findViewById(R.id.btn_udpStart);
        btnUdpSend  = (Button) findViewById(R.id.btn_Send);
        btnRcvClear = (Button) findViewById(R.id.btn_CleanRcv);
        btnSendClear= (Button) findViewById(R.id.btn_CleanSend);
        txtRcv      = (TextView) findViewById(R.id.txt_Rcv);
        txtSend     = (TextView) findViewById(R.id.txt_Send);
        editIp      = (EditText) findViewById(R.id.editIp);
        editPort    = (EditText) findViewById(R.id.editPort);
        editSend    = (EditText) findViewById(R.id.edit_Send);
    }

    private void Listening(){
        btnUdpStart.setOnClickListener(myBtnClick);
        btnUdpClose.setOnClickListener(myBtnClick);
        btnUdpSend.setOnClickListener(myBtnClick);
        btnRcvClear.setOnClickListener(myBtnClick);
        btnSendClear.setOnClickListener(myBtnClick);

    }

    private void BindReceiver(){
        IntentFilter intentFilter = new IntentFilter("udpReceiver");
        registerReceiver(myBroadcastReceiver,intentFilter);
    }

    private class MyHandler extends Handler{
        private final WeakReference<MainActivity> mActivity;
        public MyHandler(MainActivity activity) {
            mActivity = new WeakReference<MainActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = mActivity.get();
            if (null != activity){
                switch (msg.what){
                    case 1:
                        String str = msg.obj.toString();
                        txtRcv.append(str);
                        break;
                    case 2:
                        String stra = msg.obj.toString();
                        txtSend.append(stra);
                        break;
                    case 3:
                        break;
                }
            }
        }
    }

    private class MyBroadcastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            String mAction = intent.getAction();
            switch (mAction){
                case "udpReceiver":
                    String msg = intent.getStringExtra("udpReceiver");
                    Message message = new Message();
                    message.what = 1;
                    message.obj = msg;
                    myHandler.sendMessage(message);
                    break;
            }
        }
    }


    private class MyBtnClick implements Button.OnClickListener{

        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.btn_udpStart:
                    Log.i("asd","asdasd");

                    if (!editIp.getText().toString().isEmpty() && !editIp.getText().toString().isEmpty()){
                        int mPort = Integer.parseInt(editPort.getText().toString());

                        udpServer = new UdpServer(editIp.getText().toString(),mPort);
                        Thread thread = new Thread(udpServer);
                        thread.start();
                        btnUdpStart.setEnabled(false);
                        btnUdpClose.setEnabled(true);
                    }else {
                        Log.i("DebugInfo","请输入Ip或者Port");
                    }
                    break;
                case R.id.btn_udpClose:
                    btnUdpClose.setEnabled(false);
                    final Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //关闭UDP
                            udpServer.setUdpLife(false);

                            while (udpServer.getLifeMsg()); //等待udp阻塞结束,这里就体现出超时的好处了

                            Looper.getMainLooper();
                            btnUdpStart.setEnabled(true);
                        }
                    });
                    thread.start();

                    break;
                case R.id.btn_CleanRcv:
                    txtRcv.setText("");
                    break;
                case R.id.btn_CleanSend:
                    txtSend.setText("");
                    break;
                case R.id.btn_Send:
                    Thread thread1 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            if (editSend.getText().toString() != null){
                                try {
                                    udpServer.Send(editSend.getText().toString());
                                    Message message = new Message();
                                    message.what =2 ;
                                    message.obj = editSend.getText().toString();
                                    myHandler.sendMessage(message);
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }else {
                                Log.i("DebugInfo","请输入发送内容");
                            }

                        }
                    });
                    thread1.start();
                    break;
            }
        }
    }






}


最后,我们在AndroidManifest文家中,加上权限声明即可:

 

 

    <uses-permission android:name="android.permission.INTERNET"/>


写在这就全部结束了,和上次写的UDP Client做一个通信验证,实验如下图:

 

上图为UDP Server发送 im server内容,接收到了客户端发来的 im clietn内容显示在接收区

上图为UDPClent 发送im client内容,接收到服务器发送的im server内容。

 

udp服务端和客户端都验证通过。

 

附上本期Demo地址:

点击打开链接

 

 

  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值