JAVA UDP網絡編程學習筆記

一、UDP網絡編程概述

  采用TCP協議通信時,客戶端的Socket必須先與服務器建立連接,連接建立成功后,服務器端也會持有客戶端連接的Socket,客戶端的Socket與服務器端的Socket是對應的,它們構成了兩個端點之間的虛擬通信鏈路。與TCP通信不同,UDP是面向無連接的、不可靠的基于數據包的傳輸協議。即應用進程(或程序)在使用UDP協議之前,不必先建立連接。自然,發送數據結束時也沒有連接需要釋放。因此,減少了開銷和發送數據之前的延時。UDP也采用端口來區分進程。

  在java中,java.net.DatagramSocket負責接收和發送UDP數據報文,java.net.DatagramPacket表示UDP數據報。每個DatagramSocket與一個數據報套接字(包括本地主機的IP地址和本地UDP端口)綁定,每個DatagramSocket可以把UDP數據報發送給任意一個遠程DatagramSocket,也可以接收來自任意一個遠程DatagramSocket的數據報。在UDP數據報中包含了目的地址信息,DatagramSocket可以根據該信息把數據報發送的目的地。

  UDP協議是無連接的協議。客戶端的DatagramSocket與服務端DatagramSocket不存在一一對應關系,兩者無需建立連接,就能交換數據報。每個DatagramSocket對象都會與一個本地端口綁定,在此端口監聽發送過來的數據報。在服務器程序中,一般由程序顯示地為DatagramSocket指定本地端口。在客戶程序中,一般由操作系統為DatagramSocket分配本地端口,這種端口也稱為匿名端口。

二、關于DatagramSocket類和DatagramPacket類

  DatagramSocket類的構造方法如下:

  DatagramSocket()throws SocketException

  作用:構造數據報套接字并將其綁定到本地主機上任何可用的端口。套接字將被綁定到INADDR_ANY地址,IP地址由內核來選擇。

  DatagramSocket(int port)throws SocketException

  作用:創建數據報套接字并將其綁定到本地主機上的指定端口。套接字將被綁定到INADDR_ANY地址,IP地址由內核來選擇。

  DatagramSocket類的常用方法如表所示:

DatagramSocket類的常用方法
void send(DatagramPacket p) throws IOException發送一個UDP數據包。一個UDP數據包就是一個DatagramPacket對象
void receive(DatagramPacket p) throws IOException接收一個UDP數據包。一個UDP數據包就是一個DatagramPacket對象
void connect(InetAddress address,int port)將該UDPSocket變成連接型的UDPSocket
void disconnect()將該UDPSocket變成一個非連接型的UDPSocket
void close()關閉UDPSocket連接

?

?

?

?

?

?

?

  其中,UDPSocket分為“連接型”與“非連接型”兩種。默認UDPSocket是“非連接型”的,這個連接不是指向TCP那樣進行三步握手,而只是將對方信息與自己關聯在一起。

  DatagramPacket類的對象代表了一個UDP數據報包。通過UDP發送數據時,先要根據發送的數據生成一個DatagramPacket對象,然后通過DatagramSocket對象的send()方法發送這個對象。接收時,先要根據要接收數據的緩沖區生成一個Datagrampacket對象,然后通過DatagramPacket對象的receive()方法接收這個對象的數據內容。

  DatagramPacket類的構造方法分為兩類:

  一類是創建DatagramPacket對象用來接收數據報包;

  另一類是創建DatagramPacket對象用來發送數據報包。

  它們的區別是,用于發送數據報包的構造方法需要設置數據報包達到的目的地址,若是“連接型”UDP,則不需要設定目的地址,而用于接收數據報包的構造方法無須設定地址。

  用于接收數據報包的構造方法如下:

  DatagramPacket(byte[] buf,int length)

  作用:由接收緩沖區生成一個DatagramPacket對象。buf表示保存傳入數據報的緩沖區,length表示要讀取的字節數。

  DatagramPacket(byte[] buf,int offset,int length)

  作用:構造DatagramPacket對象。用來接收長度為length的數據包,并在緩沖區中指定了偏移量。

  用于發送數據報包的構造方法如下:

  DatagramPacket(byte[] buf,int length,InetAddress address,int port)

  作用:構造數據報包發送的對象,用來將長度為length的包發送到指定主機上的指定端口號。length參數要小于等于buf的長度。

  DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)

  作用:構造數據報包發送的對象,用來將長度為length且偏移量為offset的包發送到指定主機上的指定端口號。length參數要小于等于buf的長度。

DatagramPacket類的常用方法如下表:

DatagramPacket類的常用方法
byte[] getData()返回DatagramPacket對象中包含的數據
int getLength()返回發送/接收數據的長度
int getOffset()返回發送/接收數據在byte[]中的偏移
InetAddress getAddress()返回對方的IP地址。用InetAddress對象表示
int getPort()返回對方的端口號
void setData(byte[] buf,int offset,int length)設置該對象中包含的數據
void setAddress(inetaddress iaddr)設置該對象中包含的IP地址
void setPort()設置該對象中包含的端口號

?

?

?

?

?

?

?

  通過UDP發送/接收數據步驟:

  發送數據,先要根據發送的數據生成一個DatagramPacket對象,并指定發送長度和接收數據的IP地址和端口號,然后通過DatagramSocket對象的send()方法發送這個對象。

  接收數據,根據要接受收數據的緩沖區及大小生成一個DatagramPacket對象,然后通過DatagramSocket對象的receive()方法接收這個對象的數據內容。

三、UDP網絡編程練習

  練習代碼:

package com.ItHeima.WeekAct;/**服務器**/import java.net.*;public class ChatterClient extends Thread {private DatagramSocket socket;private InetAddress address;private byte[] buf = new byte[1000];private DatagramPacket packet = new DatagramPacket(buf, buf.length);//創建要發送的數據包private int id;//客戶端idpublic ChatterClient(int id) {this.id = id;try {socket = new DatagramSocket();//創建UDP套接字address = InetAddress.getByName(null);//取得本地地址} catch (SocketException e) {System.out.println("can not open socket");e.printStackTrace();System.exit(1);} catch (UnknownHostException e) {System.out.println("Can not find host");System.exit(1);}System.out.println("ChatterClient starting");start();//之后調用run()
    }public void run(){try {for(int i = 0 ; i < 25 ; i++){String outMsg = "服務器你好,這是我客戶端發過來的數據,請接收!" + id + ",消息" + i;//要發送到服務器的數據socket.send(new DatagramPacket(outMsg.getBytes(),outMsg.getBytes().length, address, ChatterServer.INPORT));//打包數據并將其發送到指定地址+端口的服務端socket.receive(packet);//接收服務端返回的數據包String msg=new String(packet.getData(),packet.getOffset(),packet.getLength());//獲取服務器返回的信息String rcvd = "客戶端--" + id +", 收到來自服務器的信息" + packet.getAddress() + "," + packet.getPort() + ":" + msg;//組合返回信息System.out.println(rcvd);//輸出到控制臺
            }} catch (Exception e) {e.printStackTrace();System.exit(1);//出錯退出
        }}public static void main(String[] args) {for(int i = 0 ; i < 10 ; i ++ ){new ChatterClient(i);}}
}
package com.ItHeima.WeekAct;/**服務器**/import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class ChatterServer {public static final int INPORT = 1711;//服務器端口private byte[] buf = new byte[1000];private DatagramPacket packet = new DatagramPacket(buf, buf.length);//創建數據包private DatagramSocket socket;//UDP套接字public ChatterServer(){try{socket = new DatagramSocket(INPORT);//啟動套接字System.out.println("Server started");while(true){socket.receive(packet);//接收數據包并將當前線程掛起String msg=new String(packet.getData(),packet.getOffset(),packet.getLength());//獲取客戶端發送的信息String rcvd ="服務器--收到來自客戶端的信息:"+ msg+ ", from adddress:" + packet.getAddress() + ",port:" + packet.getPort();//解析數據包System.err.println(rcvd);//打印數據信息String returnMasg = "服務器返回信息:你好客戶端,這是你發過來的數據:" + msg+",我將它原樣返回";DatagramPacket echo = new DatagramPacket(returnMasg.getBytes(), returnMasg.getBytes().length,packet.getAddress(), packet.getPort());//將接收到包重新包裝稱UDP數據包準備原封不動的返回給客戶端socket.send(echo);//反饋數據包
            }}catch (SocketException e) {System.out.println("Can`t open socket");System.exit(1);}catch (IOException e) {System.out.println("Communication error");e.printStackTrace();}}public static void main(String[] args) {new ChatterServer();//運行服務器
    }
}

  運行結果:

?

轉載于:https://www.cnblogs.com/zhishengyong/p/3794749.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376884.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376884.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376884.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

firefox 插件開發

IDE&#xff0c;你可以嘗試下NetBeans foxbeans這個插件。轉載于:https://www.cnblogs.com/sode/archive/2013/01/25/2876562.html

13種負載均衡算法

目錄前言&#xff08;1&#xff09;輪轉調度&#xff08;Round-Robin Scheduling&#xff09;算法&#xff08;2&#xff09;加權輪轉調度&#xff08;Weighted Round-Robin Scheduling&#xff09;算法&#xff08;3&#xff09;隨機均衡調度&#xff08;Random Scheduling&am…

對于shell腳本參數獲取時的一點小技巧

問題如下&#xff1a; 根據腳本參數的個數$#進行一個循環&#xff0c;在依次輸出每個參數$1 $2 $3...... 我有一個循環變量i $i 取到這時的i為1&#xff0c;我想使用這個1再去調用$1,也是就是打印出第一個參數 就是$($i)的意思來取到第幾個參數&#xff0c;當然$($i)是不好用的…

(轉)頁游安全攻與防,SWF加密和隱藏密匙

原文鏈接&#xff1a;http://netsecurity.51cto.com/art/201211/364775.htm 頁游&#xff0c;最最核心的就是客戶端&#xff08;swf&#xff09;與服務端的游戲通信了。游戲通信產生的封包&#xff0c;內容是否可識別&#xff0c;可篡改&#xff0c;可重放&#xff0c;處理邏輯…

C++自動類型推導 : auto 與 decltype 用法

基本用法與區別 auto 總是推導出“值類型”&#xff0c;絕不會是“引用”,如果有引用&#xff0c;auto會把引用去掉&#xff0c;推導出值類型&#xff1b; auto 可以附加上 const、volatile、*、& 這樣的類型修飾符&#xff0c;得到新的類型。 auto x 10L; // auto推導為…

C++智能指針使用指南 part1:基本使用

加粗樣式>TOC 智能指針是代理模式的具體應用&#xff0c;它使用 RAII 技術代理了裸指針&#xff0c;能夠自動釋放內存&#xff0c; 無需程序員干預&#xff0c;所以被稱為“智能指針”。 智能指針不是指針&#xff0c;而是一個對象&#xff0c;所以不要對其調用delete&…

AS3.0 BitmapData類介紹

注&#xff1a;文中的Bitmapdata和BMD均為同一意思BitmapData,BMD為其縮寫一&#xff0c;概括&#xff1a; Bitmapdata繼承Object對象&#xff0c;實現IBitmapDrawable接口&#xff0c;這個接口有什么用&#xff0c;你可以理解為Drawable,能被畫。官方介紹是&#xff1a;IBitma…

C++使用JSON的序列化與反序列化

這里使用的json解析工具為JSON for Modern C,使用的話僅需要包含頭文件。 獲取方式&#xff1a;wget https://github.com/nlohmann/json/releases/download/v3.7.3/json.hpp JSON json的序列化功能和map一樣&#xff0c;用關聯數組的"[]"來任意添加數據&#xff0c…

iOS判斷為空或者只為空格

本文轉載至 &#xff1a;http://www.cnblogs.com/superhappy/archive/2012/11/08/2761403.html 經常有需求 要判斷不能為空&#xff0c;后臺老是鄙視不做非空判斷的前端 &#xff0c;木辦法 只能寫一個。 第一種想法&#xff1a;我不就是判斷 是不是nil就可以了么。結果發現太天…

Hyper-V

Hyper-V&#xff1a;也就是虛擬化技術&#xff0c;允許終端用戶在同一臺機器上運行多個操作系統&#xff0c;支持32位和64位系統&#xff0c;可以直接在Windows 8上創建自己的虛擬機。開啟Hyper-V虛擬機需要更多的內存&#xff0c;正常運行需要至少4GB以上內存&#xff0c;所以…

sdut 1451 括號東東 DP

http://acm.sdut.edu.cn/sdutoj/problem.php?actionshowproblem&problemid1451 題意&#xff1a;中文..... 思路&#xff1a; pku有一道題&#xff0c;經典的括號匹配&#xff08;區間DP&#xff09;題目&#xff0c;那道題目是求的最長滿足條件的子串的長度&#xff0c;那…

CDN緩存替代算法

CDN緩存工作過程如下&#xff1a;用戶發出一個請求&#xff0c;如果請求被命中&#xff0c;緩存將對用戶的請求進行響應&#xff0c;返回其請求的數據&#xff1b;如果未被命中&#xff0c;緩存向上拉取用戶需要的數據&#xff0c;并對其存儲的數據進行替換。 緩存算法的意義在…

前端開發常用正則表達式

1、電話 var phone /(^[^1][0-9\-]{6,20}$)|(^(134|135|136|137|138|139|150|151|152|157|158|159|182|183|187|188|147|130|131|132|155|156|185|186|145|133|153|180|189|181|184)\d{8}$)/ 2、郵箱 var email /^([a-zA-Z0-9_.-])([a-zA-Z0-9_-])((\.[a-zA-Z0-9_-]{2,3}){1,…

android 中調用接口發送短信

轉載&#xff1a;http://ziyu-1.iteye.com/blog/1013932 android中可以通過兩種方式發送短信 第一&#xff1a;調用系統短信接口直接發送短信&#xff1b;主要代碼如下&#xff1a; Java代碼//直接調用短信接口發短信 SmsManager smsManager SmsManager.getDefault(); List…

linux 命令案例學習——文件搜索

兩個搜索文件的工具 locate ——僅僅通過文件名查找文件find ——依據文件的各種屬性在既定目錄&#xff08;包括子目錄&#xff09;里查找一個通常與文件搜索命令一起使用、處理搜索結果文件列表的命令 xargs1 locate 1.1 查找文件名中含有zip的文件名 locate zip 看下結…

Redis 緩存擊穿、緩存穿透、緩存雪崩的處理方法

常用的分布式緩存Redis單機并發量能達到萬級&#xff0c;常用的關系型數據庫MySQL一般并發量是千級&#xff0c;他們支持的并發量可能差十倍&#xff0c;所以要盡可能把流量攔截在緩存層。 緩存擊穿 一個并發訪問量比較大的key在某個時間過期&#xff0c;導致所有的請求直接打…

Java-- 異常與記錄日志

可以使用java.util.logging工具將輸出記錄在日志中。記錄日志的的功能還是很簡單的&#xff0c;下面直接鋪出代碼&#xff1a; 1 package com.exceptions;2 3 import java.io.*;4 import java.util.logging.Logger;5 6 class LoggingException extends Exception{7 private…

圖像處理基礎

圖像處理基礎 在計算機中&#xff0c;按照顏色和灰度的多少可以將圖像分為二值圖像、灰度圖像、索引圖像和真彩色RGB圖像四種基本類型。目前&#xff0c;大多數圖像處理軟件都支持這四種類型的圖像。 (1) 二值圖像&#xff1a;一幅二值圖像的二維矩陣僅由0、1兩個值構成&#x…

緩存一致性解決方法

對于緩存 數據庫讀寫&#xff0c;有個經典的Cache Aside Pattern&#xff1a; 讀取&#xff1a;先讀取緩存&#xff0c;緩存里沒有&#xff0c;讀取數據庫&#xff0c;然后返回響應&#xff0c;順便保存緩存&#xff1a; 更新&#xff1a;先更新數據庫&#xff0c;然后刪除緩…

使用SpringMVC的表單驗證

上一篇搭建了基本項目&#xff0c;這一篇在此基礎上加入表單驗證功能。 第一步&#xff0c;添加command類 Java代碼 package test.bean; import javax.validation.constraints.Size; public class User { Size(min3,max30) private String username; …