Java高级编程–网络编程
Java高级编程–网络编程
文章目录
- Java高级编程--网络编程
- 1.IP地址
- 1.1IP地址介绍
- 1.2IP地址的组成
- 1.3IP地址的配置和检测
- 1.4DNS域名解析
- 2.网络服务器
- 3.网络通信协议
- 4.Socket
- 4.1什么是Socket?
- 4.2java.net包
- 4.3基于TCP协议的Socket编程
- 4.4Socket中实现对象的传递
- 4.5多线程处理多请求
- 4.6基于UDP协议的Socket编程
1.IP地址
1.1IP地址介绍
- 什么是IP地址?为什么需要IP地址?
- 两台计算机通信, 双方都必须有地址->IP地址
- 唯一标识网络上的每一台计算机
1.2IP地址的组成
-
32位,由4个8位二进制数组成
-
IP地址 = 网络地址 +主机地址
- 网络地址:标识计算机或网络设备所在的网段
- 主机地址:标识特定主机或网络设备
1.3IP地址的配置和检测
- 查看IP地址,检测网络是否畅通
- 查看本机的IP地址<ipconfig>
- 测试网络是否通畅<ping 目标IP地址>
1.4DNS域名解析
-
访问网站时,为什么输入网址而不是IP地址?
DNS:Domain Name System,域名系统
2.网络服务器
通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机
3.网络通信协议
为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合
五层协议
- 物理层:基于电器特性的高低电压(电信号)高电压代表1低电压代表0
- 数据链路层:定义电信号的分组方式
- 网络层:引入一套新的地址来区分不同的广播域
- 传输层:端口到端口的连接通信
- 应用层(应用层,表示层,会话层):规定了数据的传输格式http,ftp
4.Socket
4.1什么是Socket?
- Socket的底层机制复杂,Java平台提供了一些简单的API,可以更简单有效的使用Socket开发而无需了解底层机制
- 通信链路的端点就被称为“套接字”(英文名Socket)
- 是提供给应用程序的接口
4.2java.net包
- Socket
- ServerSocket
- DatagramPacket
- DatagramSocket
- InetAddress
4.3基于TCP协议的Socket编程
-
基于TCP协议的Socket网络通信
- 用来实现双向安全连接网络通信
-
Socket通信模型
- 进行网络通信时,Socket需要借助数据流来完成数据的传递工作
-
三次握手和四次挥手
-
三次握手 (建立连接) ps:假设A是客户端,B是服务器
1.(A->B)携带syn数据包
A问B你能收到我的消息吗?k
2.(B->A)如果B同意连接则回复消息同意,向A发送syn+ack
B回答我收到了,你能收到我的消息吗?k
3.(A->B)A在向B发送ack数据包
A回答我收到了,开始通信
-
为什么不能用两次握手?
- 服务器收到客户端的
SYN
并回复SYN-ACK
后,只能确认自己可收、可发。但服务器无法确认客户端是否能正常接收数据(因为客户端未回复ACK
),可能会导致连接不可靠、资源浪费或数据错误。
- 服务器收到客户端的
-
四次挥手(关闭连接) ps:假设A是客户端,B是服务器
1.(A–>B)发送fin包
我要关闭,等你确认
2.(B–>A)发送ack包,此时B会进入等待关闭状态
B说稍等,等待关闭。
3.(B–>A)发送fin包,进入最后确认状态。
确认完成,可以关闭了。
4.(A–>B)A收到后回复ack包,进入超时等待状态。等待结束关闭A,B收到ack后立即关闭连接。
A确认关闭,B立即关闭。
-
为什么不能用三次挥手?
- 去掉第四次挥手(客户端的ACK),服务端发送 FIN 后,如果没有收到客户端的 ACK,服务端会一直处于最后确认状态,服务端会认为客户端没有收到 FIN,从而无法确定连接已经完全关闭。TCP协议有重传机制,如果服务端没有收到客户端的 ACK,它会重新发送 FIN。如果去掉第四次挥手,服务端会一直重传 FIN,直到超时,这会导致不必要的资源浪费。
-
Socket网络编程一般可以分成如下步骤
package com.hz.ch09.tcplx;import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
/*** 客户端(向外写数据)*/
public class ClientSocketTCP {public static void main(String[] args) {Socket socket = null;OutputStream os = null;OutputStreamWriter osw = null;Scanner scanner = new Scanner(System.in);try {//1.创建客户端Socket对象socket = new Socket("192.168.29.12", 8080);//2.从Socket中获取一个输出流,往服务器上写数据os = socket.getOutputStream();//3.将字节输出流转为字符输出流osw = new OutputStreamWriter(os);//4.写数据System.out.println("请输入要发送的内容");String data = scanner.nextLine();osw.write(data);//5.释放资源osw.close();os.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);}}
}
package com.hz.ch09.tcplx;import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;/*** 服务器端*/
public class ServerSocketTCP {public static void main(String[] args) {try {System.out.println("服务器启动了");//1.创建服务器端的ServerSocket对象ServerSocket serverSocket = new ServerSocket(8080);//2.调用accept()方法接收客户端的Socket对象Socket socket = serverSocket.accept();//3.获取输入流InputStream is = socket.getInputStream();//4.将字节流转换为字符流InputStreamReader isr = new InputStreamReader(is);char[] chars = new char[1024];int len = 0;while ((len = isr.read(chars)) != -1) {String s = new String(chars, 0, len);System.out.println(s);}//5.释放资源isr.close();is.close();socket.close();serverSocket.close();} catch (IOException e) {throw new RuntimeException(e);}}}
4.4Socket中实现对象的传递
-
序列化
package com.hz.ch09.tcplx3;import java.io.Serializable;public class UserInfo implements Serializable {private String userName;private String pwd;public UserInfo() {}public UserInfo(String userName, String pwd) {this.userName = userName;this.pwd = pwd;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", pwd='" + pwd + '\'' +'}';} }
package com.hz.ch09.tcplx3;import java.io.*; import java.net.Socket; import java.util.Scanner;public class ClientSocketTCP3 {public static void main(String[] args) {try {//1.创建一个Socket对象,指定服务器的IP地址和端口号Socket socket=new Socket("127.0.0.1",8080);//2.获取输出流,向服务器端发送信息OutputStream os=socket.getOutputStream();ObjectOutputStream oos=new ObjectOutputStream(os);oos.writeObject(getUserInfo());//3.获取输入流,读取服务器端的回复信息InputStream is=socket.getInputStream();DataInputStream dis=new DataInputStream(is);System.out.println("收到服务器端的回复:"+dis.readUTF());//4.关闭资源dis.close();is.close();oos.close();os.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);}}private static UserInfo getUserInfo(){Scanner scanner=new Scanner(System.in);System.out.print("请输入用户名:");String name=scanner.next();System.out.print("请输入密码:");String pwd=scanner.next();UserInfo userInfo=new UserInfo(name,pwd);return userInfo;}}
package com.hz.ch09.tcplx3;import java.io.DataOutputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;public class ServerSocketTCP3 {public static void main(String[] args) {try {System.out.println("服务器已启动,等待连接......");ServerSocket serverSocket = new ServerSocket(8080);Socket socket = serverSocket.accept();InputStream is = socket.getInputStream();ObjectInputStream ois = new ObjectInputStream(is);UserInfo userInfo = (UserInfo) ois.readObject();System.out.println("收到客户端发来的消息:" + userInfo.toString());String s = "登录失败";if (check(userInfo)) {s = "登录成功";}OutputStream os = socket.getOutputStream();DataOutputStream dos = new DataOutputStream(os);dos.writeUTF(s);dos.close();os.close();ois.close();is.close();socket.close();serverSocket.close();} catch (Exception e) {throw new RuntimeException(e);}}public static boolean check(UserInfo userInfo) {if ("yy".equals(userInfo.getUserName()) && "0909".equals(userInfo.getPwd())) {return true;}return false;}}
4.5多线程处理多请求
- 实现多客户请求
- 采用多线程的方式
- 一个专门负责监听的应用主服务程序
- 一个专门负责处理请求的线程程序
package com.hz.ch09.tcplx6;import java.io.Serializable;public class Student implements Serializable {private String name;private String pwd;public Student(String name, String pwd) {this.name = name;this.pwd = pwd;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}
}
package com.hz.ch09.tcplx6;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;public class Client1 {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 6666);OutputStream os = socket.getOutputStream();ObjectOutputStream oos = new ObjectOutputStream(os);Student student = new Student("杨洋", "0909");oos.writeObject(student);} catch (IOException e) {throw new RuntimeException(e);}}
}
package com.hz.ch09.tcplx6;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;public class Client2 {public static void main(String[] args) {try {Socket socket=new Socket("127.0.0.1",6666);OutputStream os = socket.getOutputStream();ObjectOutputStream oos=new ObjectOutputStream(os);Student student=new Student("陈楚生","0725");oos.writeObject(student);} catch (IOException e) {throw new RuntimeException(e);}}
}
package com.hz.ch09.tcplx6;import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;public class StuThread extends Thread {private Socket socket;public StuThread(Socket socket) {this.socket = socket;}public void run() {try {InputStream inputStream = socket.getInputStream();ObjectInputStream ois = new ObjectInputStream(inputStream);Student student = (Student) ois.readObject();System.out.println(student);} catch (Exception e) {e.printStackTrace();}}
}
package com.hz.ch09.tcplx6;import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;public class Server {public static void main(String[] args) {System.out.println("----------服务器端----------");try {ServerSocket serverSocket = new ServerSocket(6666);while (true){Socket socket = serverSocket.accept();StuThread stuThread=new StuThread(socket);stuThread.start();}} catch (Exception e) {e.printStackTrace();}}
}
4.6基于UDP协议的Socket编程
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
速度 | 慢 | 快 |
- 基于UDP协议的Socket网络编程步骤
package com.hz.ch09.udplx3;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;public class Client1 {public static void main(String[] args) {System.out.println("---------客户端1----------");Scanner scanner = new Scanner(System.in);DatagramPacket dp = null;DatagramSocket ds = null;try {//通过IP获得inetAddress对象InetAddress inetAddress = InetAddress.getByName("127.0.0.1");while (true) {System.out.print("客户端1请输入要发送的内容:");String msg = scanner.next();//封装数据包dp = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, inetAddress, 8888);ds = new DatagramSocket();ds.send(dp);//准备空数据包byte[] bytes = new byte[1024];dp = new DatagramPacket(bytes, bytes.length);//填充数据包ds.receive(dp);//解析数据包String msg1 = new String(dp.getData(), 0, dp.getLength());System.out.println("客户端1收到客户端2回复信息:" + msg1);//关闭资源ds.close();}} catch (Exception e) {e.printStackTrace();}}
}
package com.hz.ch09.udplx3;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.util.Scanner;public class Client2 {public static void main(String[] args) {System.out.println("---------客户端2----------");Scanner scanner = new Scanner(System.in);DatagramPacket dp = null;DatagramSocket ds = null;try {ds = new DatagramSocket(8888);while (true) {//准备空的数据包byte[] bytes = new byte[1024];dp = new DatagramPacket(bytes, bytes.length);//填充数据包ds.receive(dp);//解析数据包String msg = new String(dp.getData(), 0, dp.getLength());System.out.println("客户端2收到客户端1的信息:" + msg);System.out.print("客户端2请输入要回复的信息:");String msg2 = scanner.next();//客户端1的地址SocketAddress sa = dp.getSocketAddress();//封装数据包dp = new DatagramPacket(msg2.getBytes(), 0, msg2.getBytes().length, sa);//发生数据包ds.send(dp);}} catch (Exception e) {e.printStackTrace();}}
}