1. 网络编程三个关注点:IP、port、协议
- IP
IPV4:32位,127.0.0.1表示本机地址
IPV6:128位
- InetAddress
InetAddress类:表示IP地址的对象
static getByName (host) | 返回主机IP;host是主机名或IP |
getHostName () | 返回主机名 |
getHostAddress () | 返回主机IP |
InetAddress ia=InetAddress.getByName(host);
String hostName = ia.getHostName();
- port
2个字节
0~1023:知名应用等使用
1024~65535:自己使用
- 协议:网络间的通信规则
UDP:无链接
TCP:面向连接;需要先建立联系(三次握手)
2. UDP
没有客户端和服务端之分,两边都创建DatagramSocket类的对象
//发送端
public static void sendUDP(){
try {
//1. 创建socket对象
DatagramSocket ds=new DatagramSocket();
//2. 创建数据并打包------⚠️ DatagramPacket的长度参数,不要写成字符串的长度data.length()
String data="这是我发送给你的数据";
DatagramPacket dp=new DatagramPacket(data.getBytes(),data.getBytes().length,
InetAddress.getByName("192.168.xx.xx"),3000);
//3. 发送数据
ds.send(dp);
//4. 关闭发送端
ds.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//接收端
public static void recesiveDUP(){
try {
//1. 创建socket对象
DatagramSocket ds=new DatagramSocket(3000);
//2. 创建数据包,用于接收数据
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,0,bytes.length);
//3. 接收数据
ds.receive(dp);
//4. 解析数据包
bytes=dp.getData();
int len=dp.getLength();
String data=new String(bytes,0,len);
System.out.println(data);
//5. 关闭
ds.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
3. TCP
三次握手:
客户端向服务端发送连接请求
服务端向客户端发送一个响应,表示接收到了连接请求
客户端向服务端发送确认信息,确认连接
客户端创建Socket对象,服务端创建ServerSocket对象
//发送端
public static void sendTCP(){
try {
//1. 创建socket对象,第一个参数也可以直接写IP
Socket socket=new Socket(InetAddress.getByName("192.168.xx.xx"),3000);
//2. 创建输出流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//可选:数据来自键盘录入
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line=br.readLine()) != null){
if("88".equals(line)){
break;
}
//3. 发送数据---这里获取键盘录入的数据,发送出去
bw.write(line);
bw.newLine();
bw.flush();
}
socket.shutdownOutput();//发送结束标记
//可选:接收反馈
InputStream is=socket.getInputStream();
byte[] bytes=new byte[1024];
int len=is.read(bytes);
System.out.println(new String(bytes,0,len));
//4. 关闭---bw是由socket创建的,所以不用单独关闭了
// br.close();//br操作文件时,要注意关闭
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//接收端
public static void recesiveTCP(){
try {
//1. 创建socket对象
ServerSocket ss=new ServerSocket(3000);
while (true){
//2. 监听客户端了连接
Socket socket=ss.accept();
//为每个客户端开启一个线程 (//3. 创建输入流、//4. 接收数据)
new Thread(new ServerThread(socket)).start();
}//循环监听,不用close()
// ss.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ServerThread implements Runnable {
private Socket socket;
public ServerThread(Socket socket) {
this.socket=socket;
}
@Override
public void run() {
try {
//3. 创建输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//4. 接收数据
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//可选:反馈
OutputStream os = socket.getOutputStream();
os.write("我看到了你发的信息".getBytes());
//释放资源
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}