UDP通信

UDP与TCP通信原理及Android客户端实现

代码下载地址:http://download.youkuaiyun.com/detail/u011324501/9420980

UDP和TCP均指通信协议,那么,既然代表通信协议,UDP和TCP都是建立一个“通道”就可以进行服务端/客户端间的数据收发。它们的区别主要在于:UDP协议是面向非连接(不可靠)的传输协议,也就是不需要与服务端建立连接,就直接将数据发送给服务端,同时,无机制保证这条数据已成功发送给服务端。TCP协议是面向连接(可靠)的传输协议,在客户端向服务器端传输数据之前,客户端必须与服务器端通过“三次握手”来完成连接的建立,在之后的数据传输过程中,为了可靠传输,接受方还会发送ACK包来使发送方获知该数据包已经成功发送,否则,发送端将重新发送数据包直至超时或发送成功。因此,无论UDP协议还是TCP协议,均要有一个服务端先行监听某端口才能服务。

布局文件代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF66FF"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/ip"/>

        <EditText
            android:id="@+id/etremoteip"
            android:layout_width="fill_parent"
            android:inputType="none"
            android:layout_height="wrap_content"
            android:text="@string/ipaddress"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/port" />

        <EditText
            android:id="@+id/etremoteport"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:maxLength="5"
            android:text="@string/remote"/>

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/localport"/>
        <EditText
            android:id="@+id/etlocalport"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:maxLength="5"
            android:text="@string/local"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/receivedate"
            android:layout_width="fill_parent"
            android:layout_height="134dp"
            android:inputType="none" />

        <EditText
            android:id="@+id/senddate"
            android:inputType="none"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

        <Button
            android:id="@+id/btnsend"
            android:text="@string/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <TextView
        android:id="@+id/ipaddress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    
    <!-- 连接按钮 -->
    <LinearLayout
        android:layout_marginTop="15dip"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnconnect"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/connect" />

        <Button
            android:layout_marginLeft="5dip"
            android:id="@+id/btndisconnect"
            android:layout_weight="1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/disconnect"/>
    </LinearLayout>
</LinearLayout>
udpthread.java代码:

package app.udp;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.EditText;
import android.widget.Toast;

import java.io.IOException;
import java.net.*;
//import java.util.Date;
//import java.text.SimpleDateFormat;

public class udpthread implements Runnable
{
	private EditText etshowrdata = null;
	private String sRecvData;
	private Thread rthread = null;// 接收数据线程
	private DatagramSocket sUdp = null;// 发送数据Socket
	private DatagramSocket rUdp = null;// 接收数据Socket
	private DatagramPacket sPacket = null;
	private DatagramPacket rPacket = null;
	private String remoteIP;
	private int remotePort, localPort;
	private boolean isSHex = false;
	private boolean isRHex = false;
	private String currentSCodes = "UTF-8";
	private String currentRCodes = "UTF-8";
	private byte[] rBuffer = new byte[1024];//接收数据缓存1024字节
	private byte[] fBuffer = null;
	private byte[] sBuffer = null;
	
	//private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
	
	private Handler vhandler = new Handler()
	{
		@Override
		public void handleMessage(Message msg)
		{
			if (etshowrdata != null)
			{
				if (sRecvData==null) return;
				StringBuilder sb = new StringBuilder();
				sb.append(etshowrdata.getText().toString().trim());
				sb.append("\n");
				sb.append(sRecvData);
				etshowrdata.setText(sb.toString().trim());
				sb.delete(0, sb.length());
				sb = null;
			}
			// super.handleMessage(msg);
		}
	};
	
	public udpthread(EditText et)
	{
		etshowrdata = et;
	}
	
	public void setRemoteIP(String remoteIP)
	{
		this.remoteIP = remoteIP;
	}
	
	public void setRemotePort(int remotePort)
	{
		this.remotePort = remotePort;
	}
	
	public void setLocalPort(int localPort)
	{
		this.localPort = localPort;
	}
	
	public void setSHex(boolean isSHex)
	{
		this.isSHex = isSHex;
	}
	
	public void setRHex(boolean isRHex)
	{
		this.isRHex = isRHex;
	}
	
	public void setCurrentSCodes(String currentSCodes)
	{
		this.currentSCodes = currentSCodes;
	}

	public void setCurrentRCodes(String currentRCodes)
	{
		this.currentRCodes = currentRCodes;
	}

	private void startThread()
	{
		if (rthread == null)
		{
			rthread = new Thread(this);
			rthread.start();
		}
	}
	
	@SuppressWarnings("deprecation")
	private void stopThread()
	{
		if (rthread != null)
		{
			rthread.stop();
			rthread = null;
		}
	}
	
	@Override
	public void run()
	{
		while (Thread.currentThread() == rthread)
		{
			try
			{
				//不加报RuntimeException,原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。
				Looper.prepare();//
				recvData();
				vhandler.sendEmptyMessage(0);
				Thread.sleep(100);
				Looper.loop(); 
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private String recvHexData(int len)
	{
		fBuffer = new byte[len];
		System.arraycopy(rBuffer, 0, fBuffer, 0, len);
		StringBuilder sb = new StringBuilder(fBuffer.length);
		String rHex = "";
		for (int i = 0; i < fBuffer.length; i++)
		{
			rHex = Integer.toHexString(fBuffer[i] & 0xFF);
			if (rHex.length() == 1)
				rHex = "0" + rHex;
			sb.append(rHex.toUpperCase());
		}
		return sb.toString().trim();
	}
	
	private void recvData()
	{
		try
		{
			rUdp.receive(rPacket);
			if (isRHex)
				sRecvData = recvHexData(rPacket.getLength());
			else
				sRecvData = new String(rPacket.getData(),currentRCodes).trim();
			//sRecvData = String.format("[%s:%d//%s]%s", rPacket.getAddress().getHostAddress(), rPacket.getPort(), sdf.format(new Date()), sRecvData);
			sRecvData = String.format("%s", sRecvData);
		} catch (IOException ie)
		{
			System.out.println("recvdata error:" + ie.getMessage());
			Toast.makeText(MainActivity.mainActivity, "接收数据错误:" + ie.getMessage(), Toast.LENGTH_LONG);
		}
	}
	
	private boolean CharInRange(char c)
	{
		boolean result = false;
		if (c >= '0' && c <= '9')
			result = true;
		if (c >= 'a' && c <= 'f')
			result = true;
		if (c >= 'A' && c <= 'F')
			result = true;
		return result;
	}
	
	private byte StrToByte(String s)
	{
		return Integer.valueOf(String.valueOf(Integer.parseInt(s, 16))).byteValue();
	}
	
	private void SendHexData(String SData) 
	{
		int datalen = SData.getBytes().length;
		int bytelen = 0;
		if ((datalen % 2)==0)
			bytelen = (int)(datalen / 2);
		else
			bytelen = (int)(datalen / 2) + 1;
		
		sBuffer = new byte[bytelen];
		int i = 0, j = 0;
		while (i < datalen)
		{
			while (i >= 0 && (!CharInRange(SData.charAt(i))))
				i++;
			
			if (((i + 1) >= datalen) || (!CharInRange(SData.charAt(i + 1))))
			{
				sBuffer[j] = StrToByte(String.valueOf(SData.charAt(i)));
				j++;
			} else
			{
				sBuffer[j] = StrToByte(SData.substring(i, i + 2));
				j++;
			}
			
			i += 2;
		}
	}
	
	public void SendData(String SData)
	{
		try
		{
			if (sUdp==null)
				sUdp = new DatagramSocket();
			if (isSHex)
				SendHexData(SData);
			else
				sBuffer = SData.getBytes(currentSCodes);
			sPacket = new DatagramPacket(sBuffer,sBuffer.length,InetAddress.getByName(remoteIP),remotePort);
			sUdp.send(sPacket);
			sUdp.close();
			sUdp = null;
			sPacket = null;
		}catch(IOException ie)
		{
			sUdp.close();
			sUdp = null;
			sPacket = null;
			System.out.println("senddata error:" + ie.getMessage());
		}
	}
	
	public boolean ConnectSocket()
	{
		boolean result = false;
		try
		{
			if (rUdp == null)
				rUdp = new DatagramSocket(localPort);
			if (rPacket == null)
				rPacket = new DatagramPacket(rBuffer, rBuffer.length);
			startThread();
			result = true;
		} catch (SocketException se)
		{
			DisConnectSocket();
			System.out.println("open udp port error:" + se.getMessage());
		}
		return result;
	}
	
	public void DisConnectSocket()
	{
		if (rUdp != null)
		{
			rUdp.close();
			rUdp = null;
		}
		if (rPacket != null)
			rPacket = null;
		stopThread();		
	}
}
mainActivity.java代码

package app.udp;


import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Process;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity implements OnClickListener {
	private EditText etremoteip;
	private EditText etremoteport;
	private EditText etlocalport;
	private EditText etrdata;
	private EditText etsdata;
	private Button btnconnect;
	private Button btndisconnect;
	private Button btnsend;
	
	private TextView ipaddress;
	
	public static MainActivity mainActivity;
	boolean flag = false;
	private udpthread ut = null;
	
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainActivity = this;
        
        initUI();
    }
    //初始化ui
    private void initUI()
	{
		etremoteip = (EditText)findViewById(R.id.etremoteip);
		etremoteport = (EditText)findViewById(R.id.etremoteport);
		etlocalport = (EditText)findViewById(R.id.etlocalport);
		etrdata = (EditText)findViewById(R.id.receivedate);
		etrdata.setMovementMethod(ScrollingMovementMethod.getInstance());
		etsdata = (EditText)findViewById(R.id.senddate);
		ipaddress = (TextView)findViewById(R.id.ipaddress);
		ipaddress.setText("手机ip地址:"+getIP());
		
		btnconnect = (Button)findViewById(R.id.btnconnect);
		btnconnect.setOnClickListener(this);
		
		btndisconnect = (Button)findViewById(R.id.btndisconnect);
		btndisconnect.setOnClickListener(this);
		
		btnsend = (Button)findViewById(R.id.btnsend);
		btnsend.setOnClickListener(this);
		
		ut = new udpthread(etrdata);
	}


	@Override
	public void onClick(View v)
	{
		if (v.equals(btnconnect))//点击连接
		{
			String RemoteIP = etremoteip.getText().toString().trim();//IP
			int RemotePort = Integer.parseInt(etremoteport.getText().toString().trim());//远程端口号
			int LocalPort = Integer.parseInt(etlocalport.getText().toString().trim());//本地端口号
			ut.setRemoteIP(RemoteIP);
			ut.setRemotePort(RemotePort);
			ut.setLocalPort(LocalPort);
			ut.setCurrentRCodes("UTF-8");//设置接收数据格式
			ut.setCurrentSCodes("UTF-8");//设置发送数据格式
		
			if (ut.ConnectSocket()){
				flag = true;
				btnconnect.setEnabled(false);
				btndisconnect.setEnabled(true);
				Toast.makeText(getApplication(), "已连接!", Toast.LENGTH_SHORT).show();
			}
		}
		if (v.equals(btndisconnect))//断开连接
		{
			try{
				btndisconnect.setEnabled(false);
				btnconnect.setEnabled(true);
				Toast.makeText(getApplication(), "连接已断开!", Toast.LENGTH_SHORT).show();
				ut.DisConnectSocket();
				
			}catch(Exception e){
				e.printStackTrace();
			}					
		}
		if (v.equals(btnsend))//发送
		{
			String date = etsdata.getText().toString().trim();
			if (!date.trim().equals("") && flag ){
				ut.SendData(date);
			}else{
				Toast.makeText(getApplication(), "请连接或输入数据!", Toast.LENGTH_SHORT).show();
			}
		}
	}


	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		Process.killProcess(Process.myPid());
	}
	/**
	 * 获取ip地址
	 * @return ipaddress
	 */
	public String getIP(){
		//获取wifi服务
		WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
		//判断wifi是否打开
		if(!wifiManager.isWifiEnabled()){
			wifiManager.setWifiEnabled(true);
		}
		WifiInfo wifiInfo = wifiManager.getConnectionInfo();
		int ipAddress = wifiInfo.getIpAddress();
		String ip = intToIp(ipAddress);
		return ip;
	}


	/**
	 * 
	 * @param i
	 * @return
	 */
	private String intToIp(int i) {
		// TODO Auto-generated method stub	
		return (i & 0xFF) + "."+
		((i>>8) & 0xFF) + "."+
		((i>>16) & 0XFF) + "." +
		((i>>24) & 0xFF) ;
	}
	


}

权限:

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏雪羽翼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值