❶ java udp如何通過一個對象完成接收和發送數據
//注意,本地ip以及埠,廣播Ip以及埠,可根據自己的電腦實際情況定.我的三段是2
//思路:我用的udp啟動服務端,進行偵聽,如果有消息,就該頻段廣播一次..
//客戶端使用多線程,一個發送服務端,一個接受廣播..就當我復習了一次...!
importjava.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
importjava.net.InetSocketAddress;
importjava.net.SocketAddress;
importjava.util.Scanner;
publicclassUdpTest{
classSendTest{
privateintcount=1;
privateScannersc;
privatebyte[]by,by2;
privateInetAddressip;
privateSocketAddresssd1,sd2;
privateDatagramSocketds,ds2;
privateDatagramPacketdp,dp2;
SendTest(StringipName,intport)throwsException{
sc=newScanner(System.in);
ip=InetAddress.getByName(ipName);
sd1=newInetSocketAddress(ip,port);//發送的目標:ip+埠
sd2=newInetSocketAddress(19823);//己方,省略ip,默認自己本地地址
ds=newDatagramSocket();//參數為自己的標識
//接受
by2=newbyte[1024];
ds2=newDatagramSocket(sd2);
send();
}
privatevoidsend()throwsIOException{
newThread(){
publicvoidrun(){
while(true){
by=sc.nextLine().getBytes();
dp=newDatagramPacket(by,by.length,sd1);//數組,數組長度,目標ip+埠
try{
ds.send(dp);
}catch(IOExceptione){
e.printStackTrace();
}//推送服務;
System.out.println("老馬第:"+count+++"條信息發送完成!");
}
}
}.start();
newThread(){
publicvoidrun(){
while(true){
dp2=newDatagramPacket(by2,by2.length);
try{
ds2.receive(dp2);
System.out.println("老馬接受到一條廣播可能來自老宋:"+newString(by2,0,dp2.getLength()));
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}.start();
}
}
classAccepTest{
privatebyte[]by;
privateSocketAddresssd1,sd2;
privateDatagramSocketds;
privateDatagramPacketdp;
privateintcount=0;
AccepTest()throwsException{
by=newbyte[1024];
sd1=newInetSocketAddress("192.168.2.255",19823);//廣播
sd2=newInetSocketAddress(19822);//己方,省略ip,默認自己本地地址
ds=newDatagramSocket(sd2);//參數為自己的標識,這是用來接受的.....
accepts();
}
privatevoidaccepts()throwsIOException{
while(true){
count++;
System.out.println("老宋的伺服器接受第:"+count+"次數據:...");
dp=newDatagramPacket(by,by.length);//數組,數組長度,僅僅用來接收;
ds.receive(dp);//接受服務;
Stringstr=newString(by,0,dp.getLength());
System.out.println("老宋接受到數據--------->"+str);
System.out.println();
//廣播..
by=("插個廣播:"+str+"....誰發的??").getBytes();
dp=newDatagramPacket(by,by.length,sd1);
ds.send(dp);
}
}
}
publicstaticvoidmain(String[]args)throwsException{
newThread(){
publicvoidrun(){
try{
newUdpTest().newAccepTest();
}catch(Exceptione){
e.printStackTrace();
}
}
}.start();
newThread(){
publicvoidrun(){
try{
newUdpTest().newSendTest("127.0.0.1",19822);
}catch(Exceptione){
e.printStackTrace();
}
}
}.start();
}
}
❷ 請教一個JAVA UDP程序問題。我編了一個UDP通信程序,實現客戶端向伺服器端發送信息。
正如你所說
,UDP不需要實時連接,客戶端只負責發送,不保證成功,服務端也只接收正確到達的數據包,你沒有起服務端之前的客戶端所發送的UDP數據包都屬於
丟包
,就像我們玩一些網游,如果網路不好,會出現一卡一卡的,本來在這
下一秒
突然移動到
另一個地方
,中間移動的過程沒有出現,這就屬於丟包了。
❸ JAVA用udp從本地網路穿透到公網之後,從其他網路作為客戶端發送udp包到伺服器正常接收。
你說的還不清楚。Java網路編程使用Socket,同為一個網路下的主機時是肯定沒問題的,不論同一區域網或廣域網。如果內網跨越網關,我沒做過試驗,按我的理解,內網主機做客戶端,獨立主機做伺服器應該可行,反之不行。
❹ 關於java UDP文件傳輸的問題
使用UDP協議進行文件傳輸不能保證正確性,很容易發生丟包的情況。建議在進行較大文件傳輸的時候使用TCP的Socket和ServerSocket類進行傳輸。在數據量小於65600位元組的時候使用UDP是安全的
如果一定要使用UDP方式進行傳輸的話,為了提高傳輸的准確性,可以限制一下傳輸速度,方法是在發送端每次發送後sleep一下,即在發送端程序的dataSocket.send(dataPacket);一句後加上:
TimeUnit.MICROSECONDS.sleep(1);
不過這種方法也不能保證傳輸絕對准確,所以還是建議用TCP的方式
程序本身應該是能夠達到效果的,不知道錯誤提示是什麼。測試之前要看下發送端的filePath文件是否存在,貌似防火牆也有影響,測試之間最好關閉防火牆。下面是我的測試程序,接收端是類A1,接收端是類A2,發送端的文件filePath是D盤根目錄下的a1.mkv:
接收端:
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class A1 {
public static DatagramSocket dataSocket;
public static final int PORT=7;
public static byte[] receiveByte;
public static DatagramPacket dataPacket;
public static void main(String[] args) throws IOException{
dataSocket = new DatagramSocket(PORT);
DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream("D:\\a.mkv"))));
int i = 0;
while (i == 0)// 無數據,則循環
{
receiveByte = new byte[1024];
dataPacket = new DatagramPacket(receiveByte, receiveByte.length);
dataSocket.receive(dataPacket);
i = dataPacket.getLength();
// 接收數據
if (i > 0) {
// 指定接收到數據的長度,可使接收數據正常顯示,開始時很容易忽略這一點
fileOut.write(receiveByte,0,i);
fileOut.flush();
i = 0;// 循環接收
}
}
}
}
發送端:
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.util.Date;
public class A2 {
public static DatagramSocket dataSocket;
public static final int PORT=7;
public static byte[] sendDataByte;
public static DatagramPacket dataPacket;
public static void main(String[] args) throws IOException, InterruptedException{
String filePath="D:\\a1.mkv";
DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
dataSocket = new DatagramSocket(PORT+1);
sendDataByte = new byte[1024];
int read=0;
long a=new Date().getTime();
while(true){
if (fis != null) {
read = fis.read(sendDataByte);
}
if (read == -1) {
System.out.println(new Date().getTime()-a);
break;
}
dataPacket = new DatagramPacket(sendDataByte, sendDataByte.length,(Inet4Address) Inet4Address.getByName("localhost"), PORT);
dataSocket.send(dataPacket);
TimeUnit.MICROSECONDS.sleep(1);//限制傳輸速度
}
}
}
❺ 關於java用udp發送文件的問題...
我試了一下可以運行,錯誤見注釋
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import javax.swing.JFileChooser;
public class UServer {
private DatagramPacket dp; //數據報包
private DatagramSocket ds; //數據報socket
private String filename; //保存選擇的文件的名字
private FileInputStream fis; //輸入流,用來讀取磁碟文件
private FileOutputStream fos;
private byte[] buf=new byte[10240]; //位元組數組,存放讀取的文件
public UServer(){
try {
ds = new DatagramSocket(4567);
fos=new FileOutputStream("tmp/temp.dat");
dp =new DatagramPacket(buf,buf.length);
while(true){
//這個地方改成我這樣
if (dp.getData().length != 0) {
ds.receive(dp);
System.out.print(dp.getData().length);
fos.write(dp.getData());
fos.flush();
//你的while(true)是個死循環,雖然已經接收到了但是沒法循環出去,需要一個break或者把true換成你收的文件長度不等於0
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
JFileChooser jfc=new JFileChooser();
jfc.showSaveDialog(null);
filename=jfc.getSelectedFile().getPath();
try{
fos.close();
fos=new FileOutputStream(filename);
fis=new FileInputStream("tmp/temp.dat");
int c;
while((c=fis.read(buf))!= -1){
fos.write(buf);
fos.flush();
}
fos.close();
fis.close();
}catch (IOException e1){
e1.printStackTrace();
}
}
public static void main(String args[]){
new UServer();
}
}
❻ 在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;