数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

java基于UDP实现图片群发功能

来源:脚本之家  责任编辑:小易  

UDP协议(用户数据报协议)是一种不可靠的网络协议,它在通信实例的两端各建立一个Socket,但是这两个Socket之间并没有虚拟链路,这两个Socket只是发送,接收数据报的对象。

UDP的优缺点:

1. 因为UDP协议是面向非连接的协议,没有建立连接的过程,因此它的通信效率很高。很适合一些即时性很强的应用场景。

2.因为在正式通信前不必与对方先连接,不管对方状态就直接发送,至于对方是否可以收到这些数据内容,UDP无法控制,所以说UDP是一种不可靠的协议。

3.传输大小限制在64KB以下,这个尤其要注意,在做这个实例的时候,因为没有考虑到这个,直接传了一张大图,结果找了半天的原因。

Java使用DatagramSocket代表UDP协议的Socket,它唯一的作用是接收和发送数据报,至于数据究竟发给谁,DatagramSocket并不清楚;具体发送的目的地是由DatagramPacket自身决定。当Client/Server程序使用UDP协议时,实际上并没有严格的服务器和客户端的区分。通常固定IP地址,固定端口的DatagramSocket对象所在程序被称为服务器,因为有固定的IP,端口地址,其他客户端的数据报可以直接发送到服务器上。

接收数据的DatagramPacket在实例化时无需指定端口和IP地址,给出数据数据的字节数组以及长度即可。然后调用DatagramSocket的receive()方法等待数据报的到来,该方法阻塞线程直到受到一个数据报为止。

发送数据的DatagramPacket不同的是,需要给出完整的目的地,包括IP地址和端口,这样数据报才能知道将数据发给谁。当服务器接收到一个DatagramPacket对象后,如果想向该数据报的发送者反馈一些消息,但由于UDP协议是面向非连接的,所以不知道数据报是谁发送过来的,但程序可以调用DatagramPacket的getAddress()(返回一个InetAddress对象,发报的IP地址),getPort()(返回发报的端口)和getSocketAddress()(返回一个SocketAddress对象,该对象可以同时代表IP地址和端口)。

实现思路:每个客户端启动时都会向服务端发送一个字符串,该字符串代表该客户端已经上线,并在服务端将每个客户端的发报地址(即SocketAddress对象)保存在一个Set集合中。当点击任意一个上线的客户端的发送图片按钮,该图片数据就会被发送到服务端上,服务端遍历SocketAddress集合,并将图片数据转发到每个SocketAddress对应的客户端上,就实现了简单的图片群发。具体代码如下:

客户端发送数据报的工具类:

public class DatagramUtil
{
 public static final int BOADCAST_PORT = 8888;
 public static final String DEST_IP = "192.168.1.101";
 private static final int DATA_LEN = 50000;
 //定义本程序私聊的Socket实例
 private DatagramSocket singleSocket = null;
 //定义接收网络数据的字符数组
 byte[] inBuff = new byte[DATA_LEN];
 private Handler handler;

 //构造器,初始化资源
 public DatagramUtil(Handler handler) throws Exception
 {
  this.handler = handler;
  //创建用于私聊的DatagramSocket对象
  singleSocket = new DatagramSocket();
  new ReadSingle().start();
 }

 //定义单独用户发送消息的方法
 public void sendSingle(byte[] msg)
 {
  try
  {
   DatagramPacket packet = new DatagramPacket(new byte[0] , 0 , InetAddress.getByName(DEST_IP) , BOADCAST_PORT);
   packet.setData(msg);
   singleSocket.send(packet);
  }
  catch (IOException e)
  {
   e.printStackTrace();
  }
 }

 //不断地从DatagramSocket中读取数据的线程
 class ReadSingle extends Thread
 {
  byte[] singleBuff = new byte[DATA_LEN];
  private DatagramPacket singlePacket = new DatagramPacket(singleBuff , singleBuff.length);

  @Override
  public void run()
  {
   while (true)
   {
    // 读取Socket中的数据
    try
    {
     //读取Socket中的数据
     singleSocket.receive(singlePacket);
     //处理得到的消息
     Message msg = new Message();
     msg.what = 0x123;
     msg.obj = singleBuff;
     handler.sendMessage(msg);
    }
    catch (IOException e)
    {
     e.printStackTrace();
     if (singleSocket != null)
     {
      //关闭该Socket对象
      singleSocket.close();
     }
    }
   }
  }
 }
}

收到服务端发来的图片数据时,使用Handler更新UI。

public class MainActivity extends Activity
{
 private Button button;
 private ImageView img;
 private DatagramUtil datagramUtil;
 Handler handler = new Handler()
 {
  @Override
  public void handleMessage(Message msg)
  {
   if (msg.what == 0x123)
   {
    byte[] result = (byte[]) msg.obj;
    img.setImageBitmap(BitmapFactory.decodeByteArray(result , 0 , result.length));
   }
  }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main_activity);
  button = (Button) findViewById(R.id.send_img_all);
  img = (ImageView) findViewById(R.id.receiver_img);

  try
  {
   datagramUtil = new DatagramUtil(handler);
   sendData(stringYoByte());
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }

  button.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view)
   {
    sendData(bitMapToByte());
   }
  });
 }

 private void sendData(final byte[] msg)
 {
  new Thread()
  {
   @Override
   public void run()
   {
    datagramUtil.sendSingle(msg);
   }
  }.start();
 }

 public byte[] bitMapToByte()
 {
  Bitmap bitmap = BitmapFactory.decodeResource(getResources() , R.drawable.wenqing);
  ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
  bitmap.compress(Bitmap.CompressFormat.PNG , 100 , byteArray);
  bitmap.recycle();
  return byteArray.toByteArray();
 }

 public byte[] stringYoByte()
 {
  String loginStr = "hello";
  return loginStr.getBytes();
 }
}

服务端代码(运行该Java程序即可):

public class UDPServer
{
 public static final int PORT = 8888;
 private static final int DATA_LEN = 50000;
 byte[] inBuff = new byte[DATA_LEN];
 private DatagramPacket inPacket = new DatagramPacket(inBuff , inBuff.length);
 private DatagramPacket outPacket;
 private DatagramSocket serverSocket;
 private Set<SocketAddress> socketAddressList = Collections.synchronizedSet(new HashSet<SocketAddress>());

 public void init() throws IOException
 {
  serverSocket = new DatagramSocket(PORT);
  while (true)
  {
   serverSocket.receive(inPacket);
   String result = new String(inBuff , 0 , inBuff.length);
   if (result.trim().equals("hello"))
   {
    socketAddressList.add(inPacket.getSocketAddress());
   }
   else
   {
    for (Iterator<SocketAddress> iterator = socketAddressList.iterator(); iterator.hasNext() ; )
    {
     SocketAddress socketAddress = iterator.next();
     outPacket = new DatagramPacket(inBuff , inBuff.length , socketAddress);
     serverSocket.send(outPacket);
    }
   }
  }
 }

 public static void main(String[] args) throws IOException
 {
  new UDPServer().init();
 }
}

这样实现了简单的图片群发的效果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:


  • 本文相关:
  • java微信公众平台之群发接口(高级群发)
  • 利用java实现邮箱群发功能
  • java实现短信验证码和国际短信群发功能的示例
  • java、php、c#、asp实现短信群发功能的方法
  • springmvc使用jsr-303进行数据校验实例
  • 学java做项目需要学习的一些技能
  • java threadpoolexecutor 并发调用实例详解
  • java类型生命周期的详细解析
  • 详解spring boot配置排序依赖技巧
  • java编程获取当前屏幕分辨率的方法示例
  • spring boot 2.0.0 终于正式发布-重大修订版本
  • 重写hashcode()和equals()方法详细介绍
  • json 与对象、集合之间的转换的示例
  • 对比java讲解kotlin中?.与!!.的区别
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved