您好,登錄后才能下訂單哦!
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(); } }
這樣實現了簡單的圖片群發的效果。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。