湛蓝之海 发表于 2021-10-6 11:35:54

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

这篇文章主要为大家详细介绍了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;
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 , 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;
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;
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();
}
}
这样实现了简单的图片群发的效果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家。
原文链接:https://blog.csdn.net/qq_33022345/article/details/53448103

http://www.zzvips.com/article/174017.html
页: [1]
查看完整版本: java基于UDP实现图片群发功能