web开发基础
web开发基础
Servlet 是 Sun 公司推出的一种基于 Java 的动态网站开发技术。编写 Servlet 代码需要遵循 Java 语法,一个 Servlet 程序其实就是一个按照 Servlet 规范编写的 Java 类。Servlet 程序需要先编译成字节码文件(.class文件),然后再部署到服务器运行。
C/S架构
服务器-客户机,即Client-Server(C/S)结构。C/S结构通常采取两层结构。服务器负责数据的管理,客户机负责完成与用户的交互任务。
例如我们需要下载QQ、微信、电脑版吃鸡,如果该客户端软件需要升级,用户需要重新下载最新版本的客户端下载安装。
C(客户端Client)/S(Server)架构
C(客户端Client)/S(Server)架构 桌面应用程序
Javaswing、JavaFX、c#
一般的C/S架构需要下载对应的安装包,才可以使用
B/S架构
什么是web开发
Web:全球广域网,也称为万维网(www),也就是能够通过浏览器访问的网站
例如 通过浏览器访问 www.mayikt.com 、www.baidu.com、www.taobao.com。
JavaWeb开发:是使用java技术栈开发Web项目。
什么是B/S架构
B/S架构的全称为Browser/Server,即浏览器/服务器结构,Browser指的是Web浏览器
它的特点是 客户端只需要安装浏览器,应用程序的逻辑和数据都存放在服务器端共享访问。
优点:易于维护升级:服务器端升级后,客户端(浏览器端无需升级)就获取最新的版本
静态web资源(如html 页面、js、css、images):指web页面中供人们浏览的数据始终是不变。
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。
静态web资源开发技术:Html js、css、images
常用动态web资源开发技术:JSP/Servlet、ASP、PHP等
在Java中,动态web资源开发技术统称为Javaweb。
B/S体系架构的软件 版本升级的时候 客户端是无需升级的 只需要重新刷新网页即可。
缺陷:会占用服务器端带宽资源。
Http协议原理
Http基本概念
基于HTTP传输协议(超文本传输协议)客户端与服务器端之间数据传输规则
HTTP特点:
1.底层基于TCP协议实现 ,面向连接方式安全;
2.基于请求(request)与响应(response)模型
3.Http协议是无状态协议,对于事务处理是没有任何记忆功能
4.Http协议多次请求无法共享,在javaweb开发中我们可以通过cookie、session解决该问题
5.http协议数据传输过程中 属于同步的过程;如果客户端发送请求达到服务器端,服务器端已经不响应 可能会导致 客户端会一直阻塞等待 对于用户体验是不好的 所以客户端发送请求达到服务器时会设置超时时间 例如5s。
Http请求格式
1.请求行 请求方法(get、post)、url (/首页) http协议版本1.1版本 请求第一行
GET /index.html HTTP/1.1
2.请求头 (键值对的形式):包含了一些关于请求的附加信息,例如浏览器类型、请求发送时间等。
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
Accept-Language: en-US,en;q=0.8
3.请求体:post请求的最后一部分,存放发送请求的参数userName=icss&age=26
get与post请求区别
1.get请求请求的参数在请求行中,没有请求体;
2.post请求请求参数在请求体中;
3.get请求请求参数有大小限制,post请求没有
Http相应格式
HTTP响应格式由状态行、响应头和响应正文三个部分组成。
1.响应行:响应数据第一行 http协议版本1.1版本
200表示响应状态码 ok为 成功状态
200: (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
404: (未找到) 服务器找不到请求的网页。
405: (方法禁用) 禁用请求中指定的方法。
408: (请求超时) 服务器等候请求时发生超时。
5xx(服务器错误,一般是服务端问题)
2.响应头:第二行开始 格式 key value
3.响应正文:是服务器返回给客户端的数据,可以是HTML页面、JSON数据或者其他格式的数据。
<!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <h1>Hello World</h1> </body> </html>
socket
Socket是一种网络通信的方式,它定义了在网络中两个程序之间双向通信的标准。在Socket编程中,服务端和客户端各自创建一个Socket对象,用于发送和接收数据。
Socket通信的流程如下:
服务端创建Socket对象,并绑定一个IP地址和端口号,开始监听客户端的请求。
客户端创建Socket对象,并连接到服务端指定的IP地址和端口号。
服务端接受客户端的连接请求,并创建一个新的Socket对象与客户端通信。
客户端和服务端之间进行双向通信,可以发送和接收数据。
通信结束后,客户端和服务端分别关闭自己的Socket对象。
在具体实现时,根据需要选择TCP或UDP协议族中的一种。其中,TCP协议提供了可靠的连接,保证数据的顺序、完整性和可靠性,适合需要长时间稳定连接的场景。而UDP协议则是无连接的,没有建立连接过程,不保证数据传输的可靠性,但速度快,适合对实时性要求高、对数据丢失可以容忍一定的场景,例如在线游戏。
Socket编程是网络编程的重要组成部分,在各种网络应用程序中都有广泛应用。
网络通讯三要素
协议、IP地址、端口号
IP地址和端口号码
IP地址准确定位主机
1.IP 地址:InetAddress(在Java中使用InetAddress类代表IP)一的标识 Internet 上的计算机(通信实体)
2.本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
3.IP地址分类方式1:IPV4 和 IPV6
3.1 IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已 经用尽。以点分十进制表示,如192.168.0.1
3.2 IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
4.IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用
端口号就是标识正在计算机上运行的进程(程序)不同的进程有不同的端口号被规定为一个 16 位的整数 0~65535。
InetAddress
在JDK中提供了一个与IP地址相关的InetAddress类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法。
/**方法声明功能描述InetAddress getByName(String host)获取给定主机名的的IP地址,host参数表示指定主机InetAddress getLocalHost()获取本地主机地址String getHostName()获取本地IP地址的主机名boolean isReachable(int timeout)判断在限定时间内指定的IP地址是否可以访问String getHostAddress()获取字符串格式的原始IP地址*/ // 获取给定主机名的的IP地址,host参数表示指定主机 InetAddress inetAddress = InetAddress.getByName("192.168.0.106"); // 获取获取本地IP地址的主机名 String hostName = inetAddress.getHostName(); // 获取IP地址 String address = inetAddress.getHostAddress(); System.out.println("hostName:" + hostName); System.out.println("address:" + address);
UDP协议
什么是UDP协议
UDP协议 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据报的方法,俗称面向无连接。通俗易懂讲解 UDP协议会把数据打包发送给目标地址, 这个数据包能不能发送给目标地址就不管了,所以我们的udp协议 它是不可靠协议、安全性低,容易丢包 但是速度非常快 无需类似于 tcp协议三次握手。核心特点:面向无连接、不可靠的协议 、安全系数很低 容易丢包 但是传输速度是非常快 不需要类似于tcp协议三次握手。 聊天工具
发送数据
1.创建发送端socket对象;
2.提供数据,并将数据封装到数据包中;
3.通过socket服务的发送功能,将数据包发出去;
4.释放资源;
public static void main(String[] args) throws IOException { //1.创建发送端socket对象 DatagramSocket socket = new DatagramSocket(); /** * 提供数据到数据包中 * 第一个参数byte数组 * 第二个参数传递长度 * 第三个参数InetAddress对象 * 第四个参数端口号 */ byte[] msg = "wzy is icss".getBytes(); InetAddress inetAddress = InetAddress.getByName("DESKTOP-05C78ND"); int port = 8888; DatagramPacket datagramPacket = new DatagramPacket(msg, msg.length, inetAddress, port); //3.通过socket服务的发送功能,将数据包发出去 socket.send(datagramPacket); //释放资源 socket.close(); }
接收数据
1.创建接收端socket对象;
2.接收数据;
3.解析数据;
4.输出数据;
5.释放资源;
public static void main(String[] args) throws IOException { //1.创建接收端socket对象,传入要接受的端口号 DatagramSocket socket = new DatagramSocket(8888); //2.接收数据 byte[] msg = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(msg, msg.length); //3.解析数据 System.out.println("等待接收数据..."); socket.receive(datagramPacket); System.out.println("解析完成...."); //4.输出数据 System.out.println(new String(datagramPacket.getData())); //释放资源 socket.close(); }
ICP/IP协议
三次握手
第一次握手:客户端会向服务器端发送码为syn=1,随机产生一个seq_number=x的数据包到服务器端(syn)
第二次握手:服务端接受到客户端请求之后,确认ack=x+1, 于是就向客户端发送syn(服务端独立生成 随机生成数字Y)+ack
第三次握手:客户端接受syn+ack,向服务器端发送ack=y+1,此包发送完毕即可建立tcp连接。
白话文翻译:
第一次握手:客户端向服务器端发送 问服务器你在不在?
第二次握手:服务器端回应客户端说:我在的。
第三次握手:客户端发送给服务器端:ok,那我开始建立连接的
客户端
1.创建发送端Socket对象(创建连接)
2.获取输出流对象;
3.发送数据;
4.释放资源;
public static void main(String[] args) throws IOException { //创建发送端Socket对象(创建连接) Socket socket = new Socket(InetAddress.getByName("DESKTOP-05C78ND"), 8888); //获取输出流对象 OutputStream outputStream = socket.getOutputStream(); //发送数据 String msg = "我是***"; outputStream.write(msg.getBytes()); //释放资源 outputStream.close(); socket.close(); }
服务器端
1.创建接收端Socket对象;
2.监听(阻塞:如果建立连接失败,程序会一直阻塞,不往下执行;
3.获取输入流对象;
4.获取数据;
5.输出数据;
6.释放资源;
public static void main(String[] args) throws IOException { //创建接收端Socket对象 ServerSocket serverSocket = new ServerSocket(8888); //监听(阻塞:如果建立连接失败,程序会一直阻塞,不往下执行 Socket socket = serverSocket.accept(); //获取到客户端发生过来的数据 InputStream inputStream = socket.getInputStream(); //输出数据 int len = 0; byte[] msg = new byte[1024]; int line = inputStream.read(msg); System.out.println(new String(msg, 0, line)); //释放资源 inputStream.close(); serverSocket.close(); }
常见报错
Exception in thread "main" java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:75) at java.net.AbstractPlainSocketImpl
客户端连接不上服务器端 javaweb开发 http协议 底层就是基于 tcp协议封装
一般都是端口问题,或者防火墙
练习题
使用tcp协议 客户端可以一直发送数据给服务器端,服务器端可以一直接受到客户端发送的数据。如果客户端输入 666 就会直接退出程序。
也可以改造为多线程
练习题
模拟登陆测试
客户端
public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); while (true) { System.out.println("请输入你的用户名"); String username = sc.next(); System.out.println("请输入你的密码"); String password = sc.next(); //创建一个Socket对象 Socket socket = new Socket("127.0.0.1", 7777); //创建输出流对象 OutputStream outputStream = socket.getOutputStream(); //发送数据 String text = "userName = " + username + "&" + "password = " + password; outputStream.write(text.getBytes()); //接收服务器返回来的数据 InputStream inputStream = socket.getInputStream(); byte[] msg = new byte[1024]; int line = inputStream.read(msg); String s = new String(msg, 0, line); System.out.println(s); //关闭资源 inputStream.close(); socket.close(); } }
服务器端
public static void main(String[] args) throws IOException { //创建一个ServerSocket对象 ServerSocket serverSocket = new ServerSocket(7777); System.out.println("服务器启动...."); while (true) { //监听客户端传过来的数据 Socket socket = serverSocket.accept(); //创建线程不要使用new的方式,一般都需要在线程池中取出来----- new Thread(() -> { try { InputStream inputStream = socket.getInputStream(); byte[] msg = new byte[1024]; int len = inputStream.read(msg); //将该数据转化为字符串 String s = new String(msg, 0, len); //分离出用户名和密码 String[] split = s.split("&"); String username = split[0].split("=")[1].trim(); String password = split[1].split("=")[1].trim(); System.out.println(username); System.out.println(password); //回应数据给客户端 OutputStream outputStream = socket.getOutputStream(); if ("wzy".equals(username) && "3116465773".equals(password)) { outputStream.write("登录成功".getBytes()); outputStream.flush(); } else { outputStream.write("用户名或者密码错误".getBytes()); outputStream.flush(); } //关闭资源 inputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } }