网络编程
网络编程分类
C/S程序:客户端与服务器 (QQ 用户可以不更新,那么代码由于存储在用户的电脑中,就会导致部分新功能无法使用)
B/S程序:浏览器与服务器 (网站程序存在服务器,但是浏览器多数代码有规范,所以需要特定方式来写传输数据的代码,数据的组织方式是透明的)
Java进行网络编程时,由虚拟机实现了底层复杂的网络协议,Java程序只需要调用Java标准库提供的接口,就可以简单高效地编写网络程序。
只有使用TCP/IP协议的计算机才能够联入互联网,使用其他网络协议(例如NetBIOS、AppleTalk协议等)是无法联入互联网的
IP地址
IP地址用于唯一标识一个网络接口(Network Interface)一台联入互联网的计算机肯定有一个IP地址,但也可能有多个IP地址。
按照协议类型分:
- IPv4 (32位地址):如:101.202.99.12
- IPv6 (128位地址):如: I2001:0DA8:100A:0000:0000:1020:F2F3:1428
按照访问范围分:
- 公网IP地址
- 内网IP地址:常见的内网IP地址:
- 192.168.x.x
- 10.x.x.x
- 特殊地址:127.0.0.1(localhost)本机地址
如果计算机只有一个网卡,且介入了网络,那么它只有一个本机地址:127.0.0.1,以及一个接入网络的IP地址,该IP地址可以用于接入网络。
TCP协议
TCP协议可以实现数据的安全传输,应用于下载文件,浏览网页。
- TCP协议客户端与服务器相连时:存在三次握手操作,确保信息准确无误发送:
1.第一次握手:客户端向服务器端发出连接请求,等待服务器确认
2.第二次握手:服务器端向客户端回送一个响应,通知客户端收到了请求
3.第三次握手:客户端再次向服务器端发送确认信息,确认链接
完成三次握手就可以进行数据传输了,由于这种面向连接的特性,TCP协议可以保证数据传输的安全性
- TCP协议客户端与服务器断开连接时:存在四次挥手操作
TCP协议 - OSI模型
值得是从一台计算机的软件,将数据发送到一台计算机软件中的过程。
七层模型:应用层,表现层,会话层,传输层,网络层,数据链路层,物理层(通过物理网卡转发)
UDP协议
(User Datagram Protocol)用户数据报:UDP协议是个面向无连接的协议(不管接受对象是否已经启动,都发送数据),传输数据时,无需建立连接,直接将数据、数据源和目的地封装在数据包中,但是数据会丢失。应用在QQ聊天(早期)和视频会议中。
Socket
Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接。而Socket内部通过TCP/IP协议把数据传输到网络。
简单理解:可以将Socket视为(IP地址+端口号):一个应用程序和外界应用程序交换信息(数据包)的通道
- 一个Socket就是由IP地址和端口号(范围是0~65535)组成
- 端口号总是由操作系统分配
- 小于1024的端口属于特权端口(需要管理员权限),大于1024的端口可以由任意用户的应用程序打开
Socket通信原理
使用Socket时,其实就是在两个进程之间进行网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
Socket(套接字):两台计算机之间的通信端点,像两个人打电话的各自的手机
1.ServerSocket类:
搭建服务器
一定是:先有服务器,否则客户端无法连接到服务器就会崩溃
-
常用构造方法
ServerSocket(int port): ***
创建一个基于TCP/IP的服务器,并指定端口号
建议端口号:(1025~65535) -
常用方法
1.Socket accept():
等待客户端连接,此方法导致线程阻塞,直到一个客户端成功连接,返回Socket对象后还会继续运行
2.void close():
无论是Socket/ServerSocket,使用之后都应当调用关闭方法,(会执行四次挥手的过程)
2.Socket类:
搭建客户端
- 常用构造方法
Socket(String ip, int port): ***
String ip:服务器的IP地址
int port:服务器软件端口号 - 常用方法
- OutputStream getOutputStream():返回一个OutputStream类对象
- InputStream getInputStream()::返回一个InputStream类对象
- void close()
Socket中的输入/输出流
在socket中,获取输入输出流的操作,对于客户端和服务器来说是相对的
客户端的输入流( socket.getInputStream() ):获取到的是服务器的输出流中的 输出的内容
客户端的输出流( socket.getOutputStream() ):则是将客户端的输出流输出到 服务器端中
Demo
客户端
import java.net.*;
import java.io.*;
import java.util.Scanner;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
//1.连接服务器 端口号为 8888
Socket socket = new Socket("127.0.0.1", "8888");
//2.通过socket 获取 输出流
OutputStream os = socket.getOutputStream();
//3.将输出流转换为打印流
PrintStream ps = new PrintStream(os);
//4.通过socket 获取 输入流
InputStream is = socket.getInputStream();
//5.将输入流转为字符读取流 再转换为缓冲逐行读取流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (true) {
//用户循环利用打印流 向服务器 输出 想要输入的内容
System.out.println("请输入要发送给服务器的内容");
String text1 = input.nextLine();
ps.println(text1);
//输出之后 会发生阻塞 由于服务器 也会向 客户端反馈相应的输出
String text2 = br.readLine();
System.out.println(text2);
if ("goodbye".equals(text1)) {
//当用户输入goodbye之后 就会结束循环,从而客户端退出
break;
}
}
}
}
服务器端
import java.net.*;
import java.io.*;
import java.util.Scanner;
public class ServerDemo {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
//1.服务器监听 端口号为 8888
System.out.println("服务器启动,等待客户端连接")
ServerSocket server = new ServerSocket("8888");
Socket socket = server.accept();
System.out.println("一个客户端已经连接:" + socket.getInetAddress());
//2.通过socket 获取 输入流
InputStream is = socket.getInputStream();
//3.将输入流转为字符读取流 再转换为缓冲逐行读取流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//4.通过socket 获取 输出流
OutputStream os = socket.getOutputStream();
//5.将输出流转换为打印流
PrintStream ps = new PrintStream(os);
while (true) {
// 向服务器 输出 用户循环利用的打印流 想要输入的内容
String text = br.readLine();
ps.println("服务器接收到您的输入为:" + text);
ps.println("输入:goodbye 将退出服务器");
//输出之后 会发生阻塞 由于服务器 也会向 客户端反馈相应的输出
if ("goodbye".equals(text)) {
//当用户输入goodbye之后 就会结束循环,从而服务器端退出
break;
}
}
}
}