InetAddress ip = InetAddress.getByName(host);//host能夠是計算機名字也能夠是IP地址如127.0.0.1
複製代碼
在程序中使用scoket進行通訊,使用socket通訊須要指定IP、端口、協議(UDP、TCP);數據發送分爲兩步:一、第一步是監聽(等待數據發送過來),用來接收數據,需指定監聽的端口;二、第二部是發送(須要指定發送到哪一個計算機:IP地址,該計算機的哪一個程序:Port號)。編程
socket中分爲發送端和接收端:發送端通常爲客戶端,接收端通常爲服務端。數組
通常有多個客戶端,一個服務端。bash
UDP協議無需創建鏈接,直接向接收端發送數據報,不用考慮對方是否接收到數據報,只須要向接收方發送就行,至於接收方有沒有接收到發送端不用管。因此使用UDP協議進行網絡數據傳輸是不可靠的,可是速度快!微信
使用UDP協議開發發送端: 用DatagramSocket發送數據:網絡
DatagramSocket ds = new DatagramSocket();//socket套接字
複製代碼
用DatagramPacket做爲包裹(發送的數據內容):socket
byte[] buf = "你好,我想給你發送數據!".getBytes();//字節數組
int length = buf.length;//發送的長度
InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
int port = 7878;//指定接收端的監聽端口號,與接收端對應
DatagramPacket dp = new DatagramPacket(buf, length, address, port);//待發送的包裹
複製代碼
send()發送數據,close()釋放資源。ide
ds.send(dp);//發送1次
//ds.send(dp);//發送2次
...
//ds.send(dp);//發送n次
ds.close();//發送完畢,釋放資源
複製代碼
舉個栗子🌰:ui
//UDP發送端
public class Demo2_UDP_Send {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket();//socket套接字
byte[] buf = "你好,我想給你發送數據!".getBytes();//字節數組
int length = buf.length;//發送數據的長度
InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
int port = 7878;//指定接收端的端口號
DatagramPacket dp = new DatagramPacket(buf, length, address, port);//待發送的包裹
ds.send(dp);//發送
ds.close();//發送完畢,釋放資源
}
}
複製代碼
使用UDP協議開發接收端: 用DatagramSocket來監聽發送端發送過來的數據:this
DatagramSocket ds = new DatagramSocket(7878);//接收端的監聽端口
複製代碼
用DatagramPacket做爲接收數據的容器:spa
byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket dp = new DatagramPacket(buf, length);//直接做爲接收數據的容器
複製代碼
receive()接收數據,程序會在這裏等待數據的到來:
ds.receive(dp);//等待數據到來
複製代碼
與發送端同樣,接收到數據以後一樣須要釋放對象ds的資源:
ds.close();//接收到數據,釋放資源
複製代碼
舉個栗子🌰:
//UDP接收端
public class Demo3_UDP_Receive {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket(7878);//接收端的監聽端口
byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket dp = new DatagramPacket(buf, length);//直接做爲接收數據的容器
ds.receive(dp);//等待數據到來
String str = new String(dp.getData(), 0, dp.getLength());
System.out.println(str);//輸出發送過來的數據
ds.close();//接收到數據,釋放資源
}
}
複製代碼
程序運行結果:
接收端的其餘信息獲取:
dp.getAddress();//獲取發送端的IP地址
dp.getPort();//獲取發送端的端口號
複製代碼
使用UDP協議實現兩個用戶雙向聊天:
一、新建一個SendThread發送線程類:
public class SendThread extends Thread {
private int port;
public SendThread(int port) {
this.port=port;
}
@Override
public void run() {
DatagramSocket ds=null;
try {
ds = new DatagramSocket();
Scanner inputstr = new Scanner(System.in);//輸入數據
while (true) {
String str = inputstr.nextLine();
if (str.equals("end")) break;
byte[] buf = str.getBytes();//字節數組
int length = buf.length;//發送數據的長度
InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
//int port = 7878;//指定接收端的端口號
DatagramPacket dp = new DatagramPacket(buf, length, address, port);//發送包裹
ds.send(dp);//發送
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ds!=null) {//有數據傳輸,因此須要釋放資源
ds.close();
}
}
}
}
複製代碼
二、再建一個ReceiveThread接收線程類:
public class ReceiveThread extends Thread {
private int port;
public ReceiveThread(int port) {
this.port=port;
}
@Override
public void run() {
DatagramSocket ds=null;
try {
ds = new DatagramSocket(port);//指定端口號來監聽數據,與發送端發送數據包指定的端口相對應
while (true) {
byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket dp = new DatagramPacket(buf, length);//做爲接收數據的容器
ds.receive(dp);//等待數據到來
String str = new String(dp.getData(), 0, dp.getLength());
System.out.println("收到來自端口"+dp.getPort()+"的消息:"+str);//輸出發送過來的數據
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ds!=null) {//有數據傳輸,因此須要釋放資源
ds.close();
}
}
}
}
複製代碼
三、新建Chant_User01類(用戶1):
public class Chant_User01 {
public static void main(String[] args) {
new SendThread(7878).start();//用戶1的發送線程,7878端口爲用戶2的接收線程監聽端口
new ReceiveThread(7879).start();//用戶1的接收線程,7879監聽來自用戶2發送的數據
}
}
複製代碼
四、新建Chant_User02類(用戶2):
public class Chant_User02 {
public static void main(String[] args) {
new ReceiveThread(7878).start();//用戶2的接收線程,7878監聽來自用戶1發送的數據
new SendThread(7879).start();//用戶2的發送線程,7879端口爲用戶1的接收線程監聽端口
}
}
複製代碼
實現效果:
用戶1:
用戶2:
TCP協議須要經過三次握手創建鏈接,客戶端與服務端之間是一個雙向通道,既能夠發送數據(使用輸出流),也能夠接收數據(使用輸入流)。因此使用TCP協議進行網絡數據傳輸是可靠的,可是速度較慢!
使用TCP協議開發客戶端: 客戶端直接使用Socket,使用輸出流OutputStream寫入數據發送:
//TCP直接使用Socket
Socket s = new Socket("127.0.0.1", 8888);//與TCP接收端創建鏈接
//使用輸出流來傳輸數據
OutputStream output = s.getOutputStream();
output.write("ww.baidu.com".getBytes());//向服務端寫入數據
s.close();
複製代碼
使用TCP協議開發服務端: 服務端使用ServerSocket,accept()等待接收客戶端發送的TCP鏈接請求,與客戶端建立鏈接成功以後會返回一個socket對象,socket對象能夠建立輸入流InputStream接收客戶端發送的數據,也能夠建立輸出流OutputStream發送數據。
ServerSocket ss = new ServerSocket(8888);//指定服務端監聽端口
Socket client = ss.accept();//等待鏈接,創建與客戶端的鏈接
InputStream input = client.getInputStream();//使用輸入流來接收數據
byte[] buf = new byte[1024];
int length = input.read(buf);//等待客戶端發送數據
client.close();//關閉鏈接
ss.close();
複製代碼
使用TCP協議實現兩端雙向聊天功能:
一、新建TCP_Client客戶端類:
//TCP客戶端
public class TCP_Client {
public static void main(String[] args) throws Exception {
Socket s = new Socket("127.0.0.1", 8888);//與Server端創建鏈接
OutputStream output = s.getOutputStream();//使用輸出流來發送數據
InputStream input = s.getInputStream();//使用輸入流接收來自Server的數據
/**
* 匿名內部類建立一個線程來接收數據
* */
new Thread() {
public void run() {
byte[] buf = new byte[1024];//字節數組容器
int length = -1;
try {
while ((length = input.read(buf))!=-1) {//等待服務端發送數據
System.out.println(new String(buf, 0, length));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
/**
* 發送數據
* */
Scanner scanner = new Scanner(System.in);
while (true) {
String in_str = scanner.nextLine();
if (in_str.equals("end"))break;
output.write(in_str.getBytes());//向Server端寫入數據
}
s.close();//關閉鏈接
}
}
複製代碼
一、新建TCP_Server服務端類:
//TCP鏈接的服務端
public class TCP_Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);//指定服務端監聽端口
Socket client = ss.accept();//等待鏈接,創建與客戶端的鏈接
System.out.println("客戶端已鏈接進來!");
InputStream input = client.getInputStream();//使用輸入流來接收數據
OutputStream output = client.getOutputStream();//使用輸出流發送數據
/**
* 匿名內部類建立一個線程來發送數據
* */
new Thread() {
public void run() {
Scanner scanner = new Scanner(System.in);
while (true) {
String str = scanner.nextLine();
if (str.equals("end"))break;
try {
output.write(str.getBytes());//向客戶端寫入數據
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
/**
* 接收數據
* */
byte[] buf = new byte[1024];
int length = -1;
while ((length = input.read(buf))!=-1) {//等待客戶端發送數據
System.out.println(new String(buf, 0, length));
}
client.close();//關閉與客戶端的鏈接
ss.close();//關閉監聽
}
}
複製代碼
運行結果:
客戶端:
服務端:
多個客戶端發送數據,一個服務端接收數據:
一、新建TCP_Server_Many類,能夠接收多個客戶端鏈接的TCP服務端和處理多個客戶端的數據:
public class TCP_Server_Many {
public static void main(String[] args) {
new VerbClientConnect().start();//啓動服務端監聽線程監聽多個客戶端的鏈接
}
}
//監聽多個客戶端的鏈接
class VerbClientConnect extends Thread {
@Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8888);
int i=0;
while (true) {
Socket socket = serverSocket.accept();//等待請求鏈接
i++;
System.out.println("接收到一個客戶端的鏈接:Client"+i+socket.getInetAddress());
new ClientMessage(socket,i).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//處理客戶端發送的消息
class ClientMessage extends Thread {
private Socket socket;
private int i;
public ClientMessage(Socket socket, int i) {
this.socket=socket;
this.i=i;
}
@Override
public void run() {
try {
InputStream input = socket.getInputStream();//使用輸入流來接收數據
byte[] buf = new byte[1024];
int length = -1;
while ((length = input.read(buf))!=-1) {//等待客戶端發送數據
System.out.println("來自客戶端Client"+i+"的消息:"+new String(buf, 0, length));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
複製代碼
二、新建TCP_Client_Many類,能夠發送多條數據的TCP客戶端:
public class TCP_Client_Many {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 8888);//請求鏈接
OutputStream output = socket.getOutputStream();//使用輸出流來發送數據
Scanner scanner = new Scanner(System.in);
while (true) {
String str = scanner.nextLine();
if (str.equals("end"))break;
output.write(str.getBytes());//向服務端發送數據
}
socket.close();
}
}
複製代碼
運行效果:
Client1:
Client2:
Client3:
服務端:
今日寄語:
歡迎關注我的微信公衆號:桃李報春