(請觀看本人博文 —— 《詳解 網絡編程》)
DatagramSocket
概述:
這類代表一個發送和接收數據包的插座。
該類是遵循 UDP協議 實現的一個Socket類。
數據報套接字發送或者接收點的分組傳送服務。
每個發送的數據包或數據報套接字上接收單獨尋址和路由。
從一台機器發送到另一台機器的多個數據包可能會被不同的路由,
並可以以任何順序到達。
在可能的情況下,
一個新建的DatagramSocket有SO_BROADCAST套接字選項已啟用,以便允許廣播數據報傳輸。
為了收到廣播包應該將DatagramSocket綁定到通配符地址。
在一些實施方案中,廣播包,也可以接受當一個DatagramSocket綁定到一個更具體的地址。
現在,本人來展示下這個類的構造方法:
構造方法:
- DatagramSocket()
構建一個數據報套接字 ,綁定到本地主機的任何可用的端口- DatagramSocket(int port)
構建一個數據報套接字,綁定到本地主機的指定端口- DatagramSocket(int port, InetAddress laddr)
創建一個數據報套接字,綁定到指定的本地地址- DatagramSocket(SocketAddress bindaddr)
創建一個數據報套接字,綁定到指定的本地套接字地址- protected DatagramSocket(DatagramSocketImpl impl)
創建一個綁定的數據報套接字, 與指定的datagramsocketimpl相關(一般不使用)
那么,現在,本人來展示下這個類的API:
API:
- InetAddress getInetAddress()
返回此套接字連接的地址- InetAddress getLocalAddress()
獲取綁定的套接字的本地地址- int getLocalPort()
返回此套接字綁定的本地主機上的端口號- SocketAddress getLocalSocketAddress()
返回此套接字綁定到的端點的地址- int getPort()
返回此套接字連接的端口號- void close()
關閉該數據報套接字- void connect(InetAddress address, int port)
將套接字連接到這個套接字的遠程地址- void connect(SocketAddress addr)
將此套接字連接到遠程套接字地址(IP地址+端口號)- void bind(SocketAddress addr)
結合這個DatagramSocket到特定的地址和端口- void disconnect()
斷開插座- boolean getBroadcast()
如果so_broadcast啟用- DatagramChannel getChannel()
返回與此數據報套接字相關的獨特的 DatagramChannel對象,如果任何- int getReceiveBufferSize()
得到這個 DatagramSocket的so_rcvbuf期權價值,即通過平台用於該 DatagramSocket輸入緩沖區的大小。- SocketAddress getRemoteSocketAddress()
返回此套接字連接的端點的地址,或如果它是無關的 null。- boolean getReuseAddress()
如果so_reuseaddr啟用。- int getSendBufferSize()
得到這個 DatagramSocket的so_sndbuf期權價值,即緩沖區的大小由平台用於輸出在這 DatagramSocket。- int getSoTimeout()
檢索設置so_timeout。- int getTrafficClass()
獲取交通類或類型的服務在IP數據報頭的DatagramSocket發送的數據包。- boolean isBound()
返回套接字的綁定狀態。- boolean isClosed()
返回套接字是否關閉或不關閉的。- boolean isConnected()
返回套接字的連接狀態。- void receive(DatagramPacket p)
接收數據報包從這個插座。- void send(DatagramPacket p)
從這個套接字發送數據報包。- void setBroadcast(boolean on)
啟用/禁用so_broadcast。- static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
集的數據報套接字實現工廠的應用。- void setReceiveBufferSize(int size)
集so_rcvbuf選項,這 DatagramSocket指定值。- void setReuseAddress(boolean on)
啟用/禁用so_reuseaddr套接字選項。- void setSendBufferSize(int size)
集so_sndbuf選項,這 DatagramSocket指定值。- void setSoTimeout(int timeout)
啟用/禁用so_timeout以指定的超時時間,以毫秒為單位。- void setTrafficClass(int tc)
集交通類或從這個DatagramSocket發送數據報的IP數據報頭字節型服務
那么,接下來,本人來通過一個例子,來展示下部分API的使用:
例1:
題目:
右轉哥忽然被豎鋸附體,透過屏幕看向了一個未關注右轉哥的同學,現在,他倆之間要進行一輪對話,請完成相關代碼。
要求:
使用DatagramSocket類構造對象,實現下右轉哥(豎鋸附身版)和那位同學的對話
那么,本人來給出代碼:
首先是右轉哥的代碼:
package edu.youzg.about_net.about_udp.core;
import java.io.IOException;
import java.net.*;
public class UDPYouzg {
public static void main(String[] args) throws IOException {
//創建Youzg 的 UDP的Socket
DatagramSocket youzg = new DatagramSocket(8888);
//封裝數據 DatagramPacket數據報包 數據報包用來實現無連接包投遞服務。
byte[] bytes = "Hello,Students who don't pay attention to Youzg\r\nI want to play a game...".getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 6666);
//發送數據,發送數據報包
youzg.send(packet);
//接收數據
youzg.receive(packet); //阻塞的方法,如果數據沒過來,就等待在這里。
//從數據報包中取數據
byte[] data = packet.getData();
//獲取數據報包中數據的實際長度
int length = packet.getLength();
//把字節數據轉換成字符串
String s = new String(data, 0, length);
System.out.println("the guy 給你發來消息,內容是:\r\n" + s);
//釋放資源
youzg.close();
}
}
接下來實現下 該同學的代碼:
package edu.youzg.about_net.about_udp.core;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPYou {
public static void main(String[] args) throws IOException {
//創建數據報套接字並將其綁定到本地主機上的指定端口。
//創建服務端的Sokcet並暴露端口號
DatagramSocket you = new DatagramSocket(6666);
//構造 DatagramPacket,用來接收長度為 length 的數據包。
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//接收數據
you.receive(packet); //阻塞的方法,如果數據沒過來,就等待在這里。
//從數據報包中取數據
byte[] data = packet.getData();
//獲取數據報包中數據的實際長度
int length = packet.getLength();
//把字節數據轉換成字符串
String s = new String(data, 0, length);
System.out.println("Jigsaw 給你發來消息,內容是:\r\n" + s);
//回復消息
data = "I'm sorry,I'm following Youzg right now at thumb up".getBytes();
packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(), 8888);
you.send(packet);
//釋放資源
you.close();
}
}
那么,現在,本人來展示下兩人的對話過程(運行結果):
首先是 該同學 接受到信息:
接下來是 右轉哥 接收到的回復:
可以看到,上述代碼實現了兩人的一問一答的對話。
(哈哈,看到上述的聊天過程,右轉哥不禁笑出了聲)
例2:
題目:
右轉哥自從被附體之后,在無意中做了很多自己並不知道的事情,所以,他要和有的同學進行一系列交談,了解當時發生的事。請用代碼實現下他們的聊天。
要求:
編寫模擬聊天室的聊天功能,在控制台輸入語句,在控制台顯示接收到的語句
那么,本人現在來展示下代碼:
首先是 右轉哥聊天所需的代碼:
package edu.youzg.about_net.about_udp.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
public class UDPYouzg {
public static void main(String[] args) throws IOException {
//創建子線程開啟服務器,來接收消息
new Thread(new Runnable() {
@Override
public void run() {
try {
//創建服務端的Socket,並暴露端口號
DatagramSocket ds = new DatagramSocket(8888);
System.out.println("Youzg服務器已經開啟,等待連接");
while (true) {
//接收發送過來的數據
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
//從數據報包中取出數據
byte[] data = dp.getData();
int length = dp.getLength();
//取發送者的IP
String s = new String(data, 0, length);
System.out.println("the gay:" + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//在主線程給對方發消息
sendMsg();
}
private static void sendMsg() {
try {
//創建客戶端的socket
DatagramSocket ds = new DatagramSocket();
//創建鍵盤錄入對象
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("請輸入要發送消息:");
String s = bfr.readLine();
if (s.equals("byebye")) {
break;
}
byte[] bytes = s.getBytes();
//創建數據報包
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 9999);
//發送數據
ds.send(dp);
}
//釋放資源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接下來是 那位同學聊天所需的代碼:
package edu.youzg.about_net.about_udp.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPYou {
public static void main(String[] args) throws IOException {
//創建子線程開啟服務器,來接收消息
new Thread(new Runnable() {
@Override
public void run() {
try {
//創建服務端的Socket,並暴露端口號
DatagramSocket ds = new DatagramSocket(9999);
System.out.println("the guy 服務器已經開啟,等待連接");
while (true) {
//接收發送過來的數據
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
//從數據報包中取出數據
byte[] data = dp.getData();
int length = dp.getLength();
//取發送者的IP
String s = new String(data, 0, length);
System.out.println("Youzg:" + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
//在主線程給對方發消息
sendMsg();
}
private static void sendMsg() {
try {
//創建客戶端的socket
DatagramSocket ds = new DatagramSocket();
//創建鍵盤錄入對象
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("請輸入要發送消息:");
String s = bfr.readLine();
if (s.equals("byebye")) {
break;
}
byte[] bytes = s.getBytes();
//創建數據報包
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 8888);
//發送數據
ds.send(dp);
}
//釋放資源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
那么,現在,本人來展示下聊天內容(運行結果):
首先是右轉哥的聊天記錄:
接下來是那位同學的聊天記錄:
可以看到,在byebye前的對話都傳達了!
(本人 網絡編程 總集篇博文鏈接:https://www.cnblogs.com/codderYouzg/p/12419011.html)