A. java問題 UDP協議中的埠問題
在Java中操縱UDP
使用位於JDK中Java.net包下的DatagramSocket和DatagramPacket類,可以非常方便地控制用戶數據報文。
在描述它們之前,必須了解位於同一個位置的InetAddress類。InetAddress實現了Java.io. Serializable介面,不允許繼承。它用於描述和包裝一個Internet IP地址,通過三個方法返回InetAddress實例:
getLocalhost():返回封裝本地地址的實例。
getAllByName(String host):返回封裝Host地址的InetAddress實例數組。
getByName(String host):返回一個封裝Host地址的實例。其中,Host可以是域名或者是一個合法的IP地址。
DatagramSocket類用於創建接收和發送UDP的Socket實例。和Socket類依賴SocketImpl類一樣,DatagramSocket類的實現也依靠專門為它設計的DatagramScoketImplFactory類。DatagramSocket類有3個構建器:
DatagramSocket():創建實例。這是個比較特殊的用法,通常用於客戶端編程,它並沒有特定監聽的埠,僅僅使用一個臨時的。
DatagramSocket(int port):創建實例,並固定監聽Port埠的報文。
DatagramSocket(int port, InetAddress localAddr):這是個非常有用的構建器,當一台機器擁有多於一個IP地址的時候,由它創建的實例僅僅接收來自LocalAddr的報文。
值得注意的是,在創建DatagramSocket類實例時,如果埠已經被使用,會產生一個SocketException的異常拋出,並導致程序非法終止,這個異常應該注意捕獲。DatagramSocket類最主要的方法有4個:
Receive(DatagramPacket d):接收數據報文到d中。receive方法產生一個「阻塞」。
Send(DatagramPacket d):發送報文d到目的地。
SetSoTimeout(int timeout):設置超時時間,單位為毫秒。
Close():關閉DatagramSocket。在應用程序退出的? 焙潁?ǔ;嶂鞫?頭拋試矗?乇誗ocket,但是由於異常地退出可能造成資源無法回收。所以,應該在程序完成時,主動使用此方法關閉Socket,或在捕獲到異常拋出後關閉Socket。
「阻塞」是一個專業名詞,它會產生一個內部循環,使程序暫停在這個地方,直到一個條件觸發。
DatagramPacket類用於處理報文,它將Byte數組、目標地址、目標埠等數據包裝成報文或者將報文拆卸成Byte數組。應用程序在產生數據包是應該注意,TCP/IP規定數據報文大小最多包含65507個,通常主機接收548個位元組,但大多數平台能夠支持8192位元組大小的報文。DatagramPacket類的構建器共有4個:
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):從Buf數組中,取出Length長的數據創建數據包對象,目標是Addr地址,Port埠。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):從Buf數組中,取出Offset開始的、Length長的數據創建數據包對象,目標是Addr地址,Port埠。
DatagramPacket(byte[] buf, int offset, int length):將數據包中從Offset開始、Length長的數據裝進Buf數組。
DatagramPacket(byte[] buf, int length):將數據包中Length長的數據裝進Buf數組。
DatagramPacket類最重要的方法就是getData()了,它從實例中取得報文的Byte數組編碼。
B. 在javasocket網路編程中,開發基於udp協議的程序使用的套接字有哪些
Socket套接字,是由系統提供用於網路通信的技術(操作系統給應用程序提供的一組API叫做Socket API),是基於TCP/IP協議的網路通信的基本操作單元。基於Socket套接字的網路程序開發就是網路編程。
socket可以視為是應用層和傳輸層之間的通信橋梁;
傳輸層的核心協議有兩種:TCP,UDP;socket API也有對應的兩組,由於TCP和UDP協議差別很大,因此,這兩組API差別也挺大。
分類:
Socket套接字主要針對傳輸層協議劃分為如下三類:
流套接字:使用傳輸層TCP協議
TCP,即Transmission Control Protocol(傳輸控制協議),傳輸層協議;
TCP的特點:
有連接:像打電話,得先接通,才能交互數據;
可靠傳輸:傳輸過程中,發送方知道接收方有沒有收到數據.(打電話就是可靠傳輸);
面向位元組流:以位元組為單位進行傳輸.(非常類似於文件操作中的位元組流);
全雙工:一條鏈路,雙向通信;
有接收緩沖區,也有發送緩沖區。
大小不限
對於位元組流來說,可以簡單的理解為,傳輸數據是基於IO流,流式數據的特徵就是在IO流沒有關閉的情況下,是無邊界的數據,可以多次發送,也可以分開多次接收。
數據報套接字:使用傳輸層UDP協議
UDP,即User Datagram Protocol(用戶數據報協議),傳輸層協議。
UDP的特點:
無連接:像發微信,不需要接通,直接就能發數據;
不可靠傳輸:傳輸過程中,發送方不知道接收方有沒有收到數據.(發微信就是不可靠傳輸);
面向數據報:以數據報為單位進行傳輸(一個數據報都會明確大小)一次發送/接收必須是一個完整的數據報,不能是半個,也不能是一個半;
全雙工:一條鏈路,雙向通信;
有接收緩沖區,無發送緩沖區;
大小受限:一次最多傳輸64k;
對於數據報來說,可以簡單的理解為,傳輸數據是一塊一塊的,發送一塊數據假如100個位元組,必須一次發送,接收也必須一次接收100個位元組,而不能分100次,每次接收1個位元組。
原始套接字
原始套接字用於自定義傳輸層協議,用於讀寫內核沒有處理的IP協議數據。
二、UDP數據報套接字編程
UDPSocket中,主要涉及到兩類:DatagramSocket、DatagramPacket;
DatagramSocket API
DatagramSocket 創建了一個UDP版本的Socket對象,用於發送和接收UDP數據報,代表著操作系統中的一個socket文件,(操作系統實現的功能–>)代表著網卡硬體設備的抽象體現。
DatagramSocket 構造方法:
方法簽名 方法說明
DatagramSocket() 創建一個UDP數據報套接字的Socket,綁定到本機任意一個隨機埠(一般用於客戶端)
DatagramSocket(int port) 創建一個UDP數據報套接字的Socket,綁定到本機指定的埠(一般用於服務端)
DatagramSocket 方法:
方法簽名 方法說明
void receive(DatagramPacket p) 從此套接字接收數據報(如果沒有接收到數據報,該方法會阻塞等待)
void send(DatagramPacket p) 從此套接字發送數據報包(不會阻塞等待,直接發送)
void close() 關閉此數據報套接字
DatagramPacket API
代表了一個UDP數據報,是UDP Socket發送和接收的數據報,每次發送/接收數據報,都是在傳輸一個DatagramPacket對象。
DatagramPacket 構造方法:
方法簽名 方法說明
DatagramPacket(byte[] buf, int length) 構造一個DatagramPacket以用來接收數據報,接收的數據保存在位元組數組(第一個參數buf)中,接收指定長度(第二個參數length)
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 構造一個DatagramPacket以用來發送數據報,發送的數據為位元組數組(第一個參數buf)中,從0到指定長度(第二個參數length)。address指定目的主機的IP和埠號
DatagramPacket 方法:
方法簽名 方法說明
InetAddress getAddress() 從接收的數據報中,獲取發送端主機IP地址;或從發送的數據報中,獲取接收端主機IP地址
int getPort() 從接收的數據報中,獲取發送端主機的埠號;或從發送的數據報中,獲取接收端主機埠號
byte[] getData() 獲取數據報中的數據
構造UDP發送的數據報時,需要傳入 SocketAddress ,該對象可以使用 InetSocketAddress 來創建。
InetSocketAddress API
InetSocketAddress ( SocketAddress 的子類 )構造方法:
方法簽名 方法說明
InetSocketAddress(InetAddress addr, int port) 創建一個Socket地址,包含IP地址和埠號
示例1:寫一個簡單的客戶端服務程序,回顯服務(EchoSever)
在這里插入圖片描述
構建Socket對象有很多失敗的可能:
埠號已經被佔用,同一個主機的兩個程序不能有相同的埠號(這就好比兩個人不能擁有相同的電話號碼);
此處,多個進程不能綁定同一個埠號,但是一個進程可以綁定多個埠,(這就好比一個人可以擁有多個手機號),一個進程可以創建多個Socket對象,每個Socket都綁定自己的埠。
每個進程能夠打開的文件個數是有上限的,如果進程之間已經打開了很多文件,就可能導致此時的Socket文件不能順利打開;
在這里插入圖片描述
這個長度不一定是1024,假設這里的UDP數據最長是1024,實際的數據可能不夠1024.
在這里插入圖片描述
這里的參數不再是一個空的位元組數組了,response是剛才根據請求計算的得到的響應,是非空的,DatagramPacket 裡面的數據就是String response的數據。
response.getBytes().length:這里拿到的是位元組數組的長度(位元組的個數),而response.length得到的是字元的長度。
五元組
一次通信是由5個核心信息描述的:源IP、 源埠、 目的IP、 目的埠、 協議類型。
站在客戶端角度:
源IP:本機IP;
源埠:系統分配的埠;
目的IP:伺服器的IP;
目的埠:伺服器的埠;
協議類型:TCP;
站在伺服器的角度:
源IP:伺服器程序本機的IP;
源埠:伺服器綁定的埠(此處手動指定了9090);
目的IP:包含在收到的數據報中(客戶端的IP);
目的埠:包含在收到的數據報中(客戶端的埠);
協議類型:UDP;
C. java中UDP文件傳輸怎麼實現
java UDP連接,如果要發送文件的話,你只能自己定義一系列的協議
因為TCP UDP 雙方發送都是二進制數據
那麼這個實現非常復雜
得不停的發送數據,寫數據,建議使用http協議
D. java 中怎麼使用UDP
發送步驟:
使用 DatagramSocket(int port) 建立socket(套間字)服務。
將數據打包到DatagramPacket中去
通過socket服務發送 (send()方法)
關閉資源
importjava.io.IOException;
importjava.net.*;
publicclassSend{
publicstaticvoidmain(String[]args){
DatagramSocketds=null;//建立套間字udpsocket服務
try{
ds=newDatagramSocket(8999);//實例化套間字,指定自己的port
}catch(SocketExceptione){
System.out.println("Cannotopenport!");
System.exit(1);
}
byte[]buf="Hello,Iamsender!".getBytes();//數據
InetAddressdestination=null;
try{
destination=InetAddress.getByName("192.168.1.5");//需要發送的地址
}catch(UnknownHostExceptione){
System.out.println("Cannotopenfindhost!");
System.exit(1);
}
DatagramPacketdp=
newDatagramPacket(buf,buf.length,destination,10000);
//打包到DatagramPacket類型中(DatagramSocket的send()方法接受此類,注意10000是接受地址的埠,不同於自己的埠!)
try{
ds.send(dp);//發送數據
}catch(IOExceptione){
}
ds.close();
}
}
接收步驟:
使用 DatagramSocket(int port) 建立socket(套間字)服務。(我們注意到此服務即可以接收,又可以發送),port指定監視接受埠。
定義一個數據包(DatagramPacket),儲存接收到的數據,使用其中的方法提取傳送的內容
通過DatagramSocket 的receive方法將接受到的數據存入上面定義的包中
使用DatagramPacket的方法,提取數據。
關閉資源。
importjava.net.*;
publicclassRec{
publicstaticvoidmain(String[]args)throwsException{
DatagramSocketds=newDatagramSocket(10000);//定義服務,監視埠上面的發送埠,注意不是send本身埠
byte[]buf=newbyte[1024];//接受內容的大小,注意不要溢出
DatagramPacketdp=newDatagramPacket(buf,0,buf.length);//定義一個接收的包
ds.receive(dp);//將接受內容封裝到包中
Stringdata=newString(dp.getData(),0,dp.getLength());//利用getData()方法取出內容
System.out.println(data);//列印內容
ds.close();//關閉資源
}
}
E. javaudp一直傳輸怎麼回事
網路卡頓。辯寬禪javaudp一直傳輸是因為網路卡頓攜塵導致的,更換網路重新傳輸即巧讓可解決此問題。該協議是一種用戶數據傳世協議。