Android:Socket UDP通信
UDP 是User Datagram Protocol的简称,一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
1、UDP是一个无连接协议,传输数据之前源端和终端不建立连接;
2、不维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息;
3、UDP信息包的标题很短,8个字节,对于TCP的20个字节信息包的额外开销很小;
4、吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制;
5、不保证可靠交付;
6、UDP是面向报文的。
二、UDP的代码编程需要用到DatagramSocket类.java使DatagramSocket代表UDP协议的Socket,先了解一下这个类。
sever服务端创建步骤:
1、生成DatagramSocket对象,参数为端口号
DatagramSocket socket = new DatagramSocket (8888);
2、byte数组用来接收数据
byte data[] = new byte[1024];
3、DatagramPackage以包形式装载byte数组
DatagramPacket packet = new DatagramPacket(data, data.length);
4、使用DatagramPacket的receive方法接收发送方所发送的数据,是一个阻塞的方法
socket.receive(packet);
5、接收到的数据转变化成可读字符串
String result = new String(packet.getData(), packet.getOffset(), packet.getLength());
client客户端创建步骤:
1、生成DatagramSoctet对象,参数为端口号
DatagramSocket socket = new DatagramSocket (8888);
2、创建一个InetAddress对象,用于确定server客户端,参数为IP地址。
InetAddress serverAddress = InetAddress.getByName("192.168.1.103");
3、需要发送的数据转化为byte数组
String sendData= "hello word";
byte data[] = sendData.getBytes();
4、生成一个DatagramPacket对象,包含需要发送的数组,byte数组,已设置IP地址的serverAddress,和服务端一致的端口号(这里是8888)
DatagramPacket packet = new DatagramPacket(data, data.length, serverAddress, 8888);
5、发送数据,调用DatagramSocket对象的send方法
socket.send(packet);
demo演示:
这里特别强调一点的就是,网络等延时通信不能放到主线上进行通信:
/**
* Created by on 2017/5/26.
*/
public class UdpClient {
private static DatagramSocket sendUdp=null;
private static DatagramSocket recvUdp=null;
private static DatagramPacket sendPkt=null;
private static DatagramPacket recvPkt=null;
private static ReceiveThread rThread=null;
public static String remoteIP="192.168.1.216";
public static int remotePort = 60000;
public static int localPort = 60000;
public static InetAddress remoteAddr;
private static byte[] recvBuff = new byte[1024];
private static byte[] sendBuff = null;
public static void initUdp()
{
try
{
sendUdp = new DatagramSocket(0);
remoteAddr = InetAddress.getByName(remoteIP);
//接收消息
recvUdp = new DatagramSocket(localPort);
recvPkt = new DatagramPacket(recvBuff, recvBuff.length);
rThread = new ReceiveThread();
rThread.start();
} catch (SocketException e)
{
e.printStackTrace();
} catch (UnknownHostException e)
{
e.printStackTrace();
}
}
public static void SendMessage(String jsonObject)
{
try
{
sendBuff = jsonObject.getBytes("UTF-8");
sendPkt = new DatagramPacket(sendBuff, sendBuff.length, remoteAddr, remotePort);
try
{
//sendUdp.send(sendPkt);
recvUdp.send(sendPkt);
} catch (IOException e)
{
e.printStackTrace();
}
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
/**
* 接收数据
*/
private static class ReceiveThread extends Thread
{
@Override
public void run()
{
super.run();
while (true)
{
if (recvUdp != null)
{
try
{
recvUdp.receive(recvPkt); //接收数据
Message msg = new Message();
msg.what = 0x01;
msg.obj = new String(recvPkt.getData());
//System.out.println(msg.obj.toString());
MainActivity.handler.sendMessage(msg);
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
}
在Activity中开启线程进行通信:
final UdpClient udp=new UdpClient();
//发送所需要的信息
new Thread(){
@Override
public void run() {
super.run();
udp.initUdp();
udp.SendMessage("1");
}
}.start();
//接受服务器返回的状态
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==0x01){
btn_main_mode.setText("手动");
btn_main_mode.setBackgroundColor(Color.BLUE);
}
}
};
在这段程序中,用handle 进行主线程和通信线程的通信,数据传递。同时最后不要忘记,要对所受用的权限进行注册。