UDP通信简单 小结
Posted tags: 篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UDP通信简单 小结相关的知识,希望对你有一定的参考价值。 android手机版和电脑版 效果图: 通过WiFi局域网 电脑和手机连接通信. 电脑版本和手机版本使用了相同的消息发送头协议, 可以相互接收消息. 若有做的不好的地方还希望大家指导一下. 1. 手机版 添加权限 AndroidManifest.xml 页面 activity_main.xml 后台代码 MainActivity.java 以下是类库代码: 获取IP地址 IPUtils.java 可要可不要 发送接收消息包装类库 :MessageEntity.java 管理消息类(主要是针对发送消息过大,分批发送使用) : MessageManage.java UDP端口发送监听类 UdpEntitiy.java 用于发送消息和监听消息 以上是关于UDP通信简单 小结的主要内容,如果未能解决你的问题,请参考以下文章 linux网络编程之用socket实现简单客户端和服务端的通信(基于UDP) <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<RelativeLayout 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" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="连接" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="发送" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fadingEdge="vertical"
android:scrollbars="vertical" >
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Large Text"/>
</ScrollView>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
package com.example.udppacket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.java.net.IPUtils;
import com.java.net.MessageEntity;
import com.java.net.UdpEntitiy;
import com.java.net.UdpEntitiy.ReceivesListener;
public class MainActivity extends ActionBarActivity {
EditText ip;
EditText send;
TextView txt;
TextView msgs;
UdpEntitiy udp;
@Override
protected void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ip = (EditText) findViewById(R.id.editText1);
send = (EditText) findViewById(R.id.editText2);
txt = (TextView) findViewById(R.id.textView1);
msgs = (TextView) findViewById(R.id.textView2);
send.setText("Hello Word!");
txt.setText("");
msgs.setText("");
ip.setText(IPUtils.getHostIP());
udp = UdpEntitiy.getUdpEntitiy();
/**
* 监听消息
* */
udp.onReceiveMessage(new ReceivesListener() {
@Override
public void onReceiveMessage(MessageEntity messageEntity) {
// TODO Auto-generated method stub
Message msg = new Message();
msg.obj = messageEntity;
msgHd.sendMessage(msg);
}
});
// 连接
findViewById(R.id.button1).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!udp.isReceive()) {
udp.startReceive();
Toast.makeText(MainActivity.this, "已连接!", Toast.LENGTH_SHORT).show();
}else {
udp.stopReceive();
Toast.makeText(MainActivity.this, "已关闭!", Toast.LENGTH_SHORT).show();
}
}
});
// 发送
findViewById(R.id.button2).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!send.getText().toString().equals("")) {
udp.send(ip.getText().toString(), send.getText().toString());
msgs.append("我 : " + send.getText().toString() + "\\n");
send.setText("");
}else {
Toast.makeText(MainActivity.this, "请输入消息!", Toast.LENGTH_SHORT).show();
}
}
});
}
Handler msgHd = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
MessageEntity me = (MessageEntity) msg.obj;
if (me.type.equals("00")) {// 文字
msgs.append("来自 [ " + me.sendIP + " ] :" + me.getString() + "\\n");
}
};
};
}
package com.java.net;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
public class IPUtils {
/***
*
* <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
* /
/**
* 获取ip地址
* @return
*/
public static String getHostIP() {
String hostIp = null;
try {
Enumeration nis = NetworkInterface.getNetworkInterfaces();
InetAddress ia = null;
while (nis.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) nis.nextElement();
Enumeration<InetAddress> ias = ni.getInetAddresses();
while (ias.hasMoreElements()) {
ia = ias.nextElement();
if (ia instanceof Inet6Address) {
continue;// skip ipv6
}
String ip = ia.getHostAddress();
if (!"127.0.0.1".equals(ip)) {
hostIp = ia.getHostAddress();
break;
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return hostIp;
}
/*
**
* 获取本机IPv4地址
*
* @param context
* @return 本机IPv4地址;null:无网络连接
*/
public static String getIpAddress(Context context) {
// 获取WiFi服务
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// 判断WiFi是否开启
if (wifiManager.isWifiEnabled()) {
// 已经开启了WiFi
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ip = intToIp(ipAddress);
return ip;
} else {
// 未开启WiFi
return getIpAddress();
}
}
private static String intToIp(int ipAddress) {
return (ipAddress & 0xFF) + "." +
((ipAddress >> 8) & 0xFF) + "." +
((ipAddress >> 16) & 0xFF) + "." +
(ipAddress >> 24 & 0xFF);
}
/**
* 获取本机IPv4地址
*
* @return 本机IPv4地址;null:无网络连接
*/
private static String getIpAddress() {
try {
NetworkInterface networkInterface;
InetAddress inetAddress;
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
networkInterface = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
return inetAddress.getHostAddress();
}
}
}
return null;
} catch (SocketException ex) {
ex.printStackTrace();
return null;
}
}
}
package com.java.net;
import java.io.ByteArrayOutputStream;
import java.io.File;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
* 标识 000000, 6位 类型00... , 00 :字符串, 01 :图片, 02 :文件 ... 2位(不足使用字母代替) 是否接收确认0 - 1
* , 0 :不确认 ,1 :确认 1位 默认不确认0 是否为最后一个 0 - 1, 0 :不是最后一个, 1 :最后一个 1位 默认最后一个1
* 数据byte[]
* */
public class MessageEntity {
// 初始化
private void init() {
flagNo = getRandom();// 6 位随机数
type = "00";
isPass = "0";
isLast = "1";
}
public MessageEntity() {
init();
}
public MessageEntity(String s){
init();
type = "00";//字符串
datas = s.getBytes();
}
public MessageEntity(File s){
init();
type = "02";//文件
//文件流转换
}
public MessageEntity(Bitmap s){
init();
type = "01";//Bitmap 图片
datas = Bitmap2Bytes(s);
}
//根据字节获取图片
public Bitmap getBitmap(){
if (datas != null && datas.length > 0) {
return Bytes2Bimap(datas);
}
return null;
}
//根据字节获取字符串
public String getString(){
if (datas != null && datas.length > 0) {
return new String(datas, 0, datas.length);
}
return null;
}
//根据字节获取文件
public String getFile(){
if (datas != null && datas.length > 0) {
//代码
return null;
}
return null;
}
//获取头字节
public byte[] getHeadToByte(){
return (getFlagNo() + "," + type + "," + isPass + "," + isLast).getBytes();
}
//根据字节 重置头部参数
public MessageEntity resetParameter(byte[] b, MessageEntity m){
if (m == null) {
m = new MessageEntity();
}
if (b != null && b.length > 0) {
String s = new String(b, 0, b.length);
resetParameter(s,m);
}
return m;
}
//根据字节 重置头部参数
public MessageEntity resetParameter(String b, MessageEntity m){
String[] ss = b.split(",");
if (ss.length >= 4) {
m.flagNo = ss[0];
m.type = ss[1];
m.isPass = ss[2];
m.isLast = ss[3];
}
return m;
}
private String flagNo;// 消息编号
public String getFlagNo(){
return flagNo;
}
public String type;// 消息类型
public String isPass;// 是否确认
public String isLast;// 是否为最后一条
public boolean isReader;//消息是否已读
public byte[] datas;// 数据字节
public String sendIP;// 发送方 IP
public int sendPort;// 发送方 端口
// 字节转为为图片
private Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
// 将图片转为字节
private byte[] Bitmap2Bytes(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
//产生随机数并凑够6位
private String getRandom() {
int r = (int) (Math.random() * 1000000);
String a = Integer.toString(r);
return getFormatString(a, 6);
}
private String getFormatString(String s, int n) {
n = n - s.length();
for (int i = 0; i < n; i++) {
s = "0" + s;// 为了凑够6位数
}
return s;
}
}
package com.java.net;
import java.util.ArrayList;
import java.util.List;
/**
* 消息管理
* */
public class MessageManage {
private MessageManage(){
list = new ArrayList<MessageEntity>();
}
private static MessageManage msgm = new MessageManage();
public static MessageManage getMessageManage(){
return msgm;
}
private static List<MessageEntity> list;
//添加
public void add(MessageEntity me){
if (list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
MessageEntity dd = list.get(i);
if (dd.getFlagNo().equals(me.getFlagNo())) {
dd.datas = addBytes(dd.datas,me.datas);
return;
}
}
}
//新添加时, 如果数量大于 max则移除所有
if (size()>MaxSize) {
for (int i = 0; i < list.size(); i++) {
MessageEntity dd = list.get(i);
if (dd.isReader) {
list.remove(i);//移除已读消息
}
}
}
list.add(me);
}
final int MaxSize = 500;//如果大于500条则自动清理
//读取消息
public MessageEntity reader(MessageEntity me){
for (int i = 0; i < list.size(); i++) {
MessageEntity dd = list.get(i);
if (dd.getFlagNo().equals(me.getFlagNo())) {
//设置为已读
dd.isReader = true;
return dd;
}
}
return null;
}
public static int size(){
return list.size();
}
//合并两个字节数组
public static byte[] addBytes(byte[] data1, byte[] data2) {
byte[] data3 = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, data3, 0, data1.length);
System.arraycopy(data2, 0, data3, data1.length, data2.length);
return data3;
}
}
package com.java.net;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import android.graphics.Bitmap;
import android.os.Message;
public class UdpEntitiy{
private UdpEntitiy(){
}
private static UdpEntitiy udp = new UdpEntitiy();
public static UdpEntitiy getUdpEntitiy(){
return udp;
}
private int port = 12345;//监听端口
private int getPortSend() {//临时端口 发送时使用
return (port + 1);
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
private boolean isReceive;//是否监听
public boolean isReceive() {
return isReceive;
}
public void startReceive(){
if (!isReceive) {//如果没有监听
new Thread(){
public void run() {
receiveMessage();
};
}.start();
}
}
//发送消息
public void send(final String ip,final MessageEntity ms){
new Thread(){
public void run() {
sendMessage(ip,ms);
};
}.start();
}
//发送文字
public void send(final String ip,String s){
final MessageEntity ms = new MessageEntity(s);
send(ip,ms);
}
//发送图片
public void send(final String ip,Bitmap s){
final MessageEntity ms = new MessageEntity(s);
send(ip,ms);
}
//发送文件
public void send(final String ip,File s){
final MessageEntity ms = new MessageEntity(s);
send(ip,ms);
}
public void stopReceive(){
if (isReceive) {//如果监听
socket.close();
}
}
//接收消息接口
public interface ReceivesListener extends EventListener{
//当接收到消息时
public void onReceiveMessage(MessageEntity messageEntity);
}
private Collection listeners = new HashSet();
public void onReceiveMessage(ReceivesListener receiveListener){
if (listeners == null) {
listeners = new HashSet();
}
listeners.add(receiveListener);
}
private void notifyListener(MessageEntity s){
if (listeners != null) {
Iterator iter = listeners.iterator();
while (iter.hasNext()) {
ReceivesListener r = (ReceivesListener) iter.next();
r.onReceiveMessage(s);
}
}
}
DatagramSocket socket = null;//声明 数据报套接字
final int VALUE_MAX = 2048;//接收发送最大字节 2kb
LinkedList flags = new LinkedList();
MessageManage msgm = MessageManage.getMessageManage();
//监听数据接收
private void receiveMessage(){
try {
socket = new DatagramSocket(port);//初始化 数据报套接字
isReceive = true;//设置状态 - 已经在监听
while (true) {
byte data[] = new byte[VALUE_MAX];//接收存放的字节
DatagramPacket packet = new DatagramPacket(data, data.length);//声明初始化接收的数据包
//阻塞监听
socket.receive(packet);
//接收到端口数据消息
MessageEntity me = new MessageEntity();
//截获返回符
if (packet.getLength() == me.getFlagNo().length()) {
flags.add(new String(packet.getData(),packet.getOffset(),packet.getLength()));
continue;
}
me.sendIP = packet.getAddress().getHostAddress();
me.sendPort = packet.getPort();
//设置头部信息
int headSize = me.getHeadToByte().length;
me.resetParameter(new String(packet.getData(),packet.getOffset(),headSize), me);
//获取有效字节
byte ndata[] = new byte[packet.getLength()-headSize];
System.arraycopy(packet.getData(),headSize,ndata,0,ndata.length);
me.datas = ndata;//赋值
//添加到消息中
msgm.add(me);
if (me.isLast.equals("1")) {//最后一个
me = msgm.reader(me);
notifyListener(me);//通知
}
}
} catch (SocketException e) {
//socket 关闭是会抛异常, 才可以停止消息阻塞
} catch (IOException e) {
}finally{
isReceive = false;
if (socket!=null