網絡編程概述:
實現網絡互連的不同計算機上運行的程序間可以進行數據交換。
網絡編程三要素:
IP地址、端口、協議
IP地址:
網絡中計算機的唯一標識符
IP地址的組成:
網絡號段+主機號段
兩個DOS命令:
ipconfig 查看本機IP地址
ping 後面跟IP地址。測試本機與指定的IP地址間的通信是否有問題
特殊的IP地址:
127.0.0.1 迴環地址(表示本機)
X.X.X.255 廣播地址
X.X.X.0 網絡地址
端口號:
正在運行的程序的標識。
有效端口:0~65535,其中0~1024系統使用或保留端口。(建議使用10000以上的端口)
協議:
通信的規則
UDP:
將數據源和目的封裝成數據包中,不需要建立連接;每個數據報的大小限制在64K;因無連接,是不可靠協議;不需要建立連接,速度快。
TCP:
建立連接,形成傳輸數據的通道;在連接中進行大數據量傳輸;通過三次握手完成連接,是可靠協議;必須建立連接,效率會稍低。
Socket編程,
即網絡編程,也叫套接字編程。
Socket包含了:IP地址+端口
Socket原理機制:
通信的兩端都有Socket。網絡通信其實就是Socket間的通信。數據在兩個Socket間通過IO傳輸。
UDP連接
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* UDP協議發送數據:
* A:創建發送端Socket對象
* B:創建數據,並把數據打包
* C:調用Socket對象的發送方法發送數據包
* D:釋放資源
* */
public class SendDemo {
public static void main(String[] args) throws IOException {
//創建發送端Socket對象
//DatagramSocket()
DatagramSocket ds = new DatagramSocket();
//創建數據,並把數據打包
//DatagramPacket(byte[] buf, int lenth, InetAddress address, int port)
//創建數據
byte[] bys = "hello,udp,我來了".getBytes();
//長度
int length = bys.length;
//IP地址對象
InetAddress address = InetAddress.getByName("192.168.0.104");
//端口
int port = 10086;
DatagramPacket dp = new DatagramPacket(bys, length, address, port);
//調用Socket對象的發送方法發送數據包
//public void send(DatagramPacket p)
ds.send(dp);
//釋放資源
ds.close();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* UDP協議接受數據:
* A:創建接受端Socket對象
* B:創建一個數據包(接收容器)
* C:調用Socket對象的接收方法接收數據
* D:解析數據包,並顯示在控制檯
* E:釋放資源
* */
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//創建接收端Socket對象
//DatagramSocket(int port)
DatagramSocket ds = new DatagramSocket(10086);
//創建一個數據包(接受容器)
//DatagramPacket(byte[] buf, int length)
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length);
//調用Socket對象的接收方法接收數據
//public void receive(DatagramPacket p)
ds.receive(dp); //阻塞式
//解析數據包,並顯示在控制檯
//獲取對方IP
//public InetAddress getAddress()
InetAddress address = dp.getAddress();
String ip = address.getHostAddress();
//public byte[] getData():獲取數據緩衝區
//public int getLength():獲取數據實際長度
byte[] bys2 = dp.getData();
int len = dp.getLength();
String s = new String(bys2,0,len);
System.out.println(ip + "傳遞的數據是:" + s);
//釋放資源
ds.close();
}
}
多線程UDP連接
import java.io.IOException;
import java.net.DatagramSocket;
public class ChatRoom {
public static void main(String[] args) throws IOException{
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(12306);
SendThread st = new SendThread(dsSend);
ReceiveThread rt = new ReceiveThread(dsReceive);
Thread t1 = new Thread(st);
Thread t2 = new Thread(rt);
t1.start();
t2.start();
}
}
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 SendThread implements Runnable {
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
// 封裝鍵盤錄入數據
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
// 創建數據並打包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.0.104"), 12306);
// 發送數據
ds.send(dp);
}
// 釋放資源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveThread implements Runnable {
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true) {
// 創建一個包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 接收數據
ds.receive(dp);
// 解析數據
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("來自" + ip + "的消息:" + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP連接
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/*
* TCP協議發送數據:
* A:創建發送端的Socket對象
* 這一步如果成功,就說明連接已經建立成功
* B:獲取輸出流,寫數據
* C:釋放資源
*
* */
public class ClienDemo {
public static void main(String[] args) throws IOException {
// 創建發送端的Socket對象
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.0.104"), 12306);
Socket s = new Socket("192.168.0.104", 12306);
// 獲取輸出流,寫數據
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我來了".getBytes());
// 釋放資源
s.close();
}
}
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創建接收端的Socket對象
// ServerSocket(int port)
ServerSocket ss = new ServerSocket(12306);
// 監聽客戶端連接。返回一個對應的Socket對象
// public Socket accept()
Socket s = ss.accept(); // 偵聽並接受到此套接字的連接。此方法在連接傳入之前一直阻塞
// 獲取輸入流,讀取數據顯示在控制檯
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String str = new String(bys, 0, len);
System.out.println(str);
// 釋放資源
s.close();
// ss.close(); //這個不應該關閉,服務器應開啓監聽客戶端
}
}