局域网(LAN),一个上课的机房,多个连在同一个路由器上的设备,就是在一个局域网中---打游戏 (局域网内的主机之间能方便的进行网络通信,又称为内网;局域网和局域网之间在没有连接的情况下,是无法通信的)
广域网(WAN) ,-更大的局域网,---格局打开不仅可以打游戏,看网页,看视频,买东西...(通过路由器,将多个局域网连接起来,在物理上组成很大范围的网络,就形成了广域网。广域网内部的局域网都属于其子网。)
咱们直接举一个例子:
网友见面: 在北方的小明去找在南方的小芳,并且约在一家咖啡馆,但是咖啡馆男生女生人也很多,所以约定~~他俩都穿红衣服见面---好,三个问题来了---这句话表明了: 从哪里去哪里,谁找谁,怎么发现对方—nice! 所以
~所以 对于为了进行网络通信:我们需要什么呢? 明确三点
~首先,从哪里访问哪里? 北方到南方 -定位网络主机-IP地址 源IP 目的IP
~其次,谁要访问谁? 小明找小芳 -定位主机中的进程-端口号 源端口 目的端口
~然后,怎么访问? 穿红衣 -协议
~~~补充一下:从北方去南方找人的的人很多,那么怎么具体对应到小明小芳~就是端口号
对于上述三点的详细介绍:
IP地址:
端口号:
协议:
知名协议端口: 系统端口号范围为 0 ~ 65535,其中:0 ~ 1023 为知名端口号,这些端口预留给服务端程序绑定广泛使用的应用层协议
协议分层:
两种典型的协议分层:
概念过于枯燥,所以!!!
我们继续唠唠小明和小芳~~~ 他们两个见面了,对对方都很满意,之后,两个人总聊天~快到小芳生日了,小明,就去淘宝下单了520色号口红~~~
okk这里是正儿八经的概念:
5.封装和分用
数据从上到下, 层层添加信息的过程, 称''封装'', 分用即为封装的逆过程
称谓: 不同的协议层对数据包有不同的称谓,在传输层叫做段,在网络层叫做数据报,在链路层叫做帧。
这个栗子不是很好举~那先给张图
肯定肯定看不懂,没关系,建议你去搜寻一下,协议~~咳咳TCP我更过的 !
就是 操作系统给应用程序提供的API
应用程序可以通过socket API来进行网络编程
网络传输层有很多种协议:最知名TCP UDP—工作特性差别大,操作系统提供了两组API
2)简单说一下TCP, UDP区别:
TCP | UDP |
有连接 | 无连接 |
可靠传输 | 不可靠传输 |
面向字节流 | 面向数据报 |
全双工 | 全双工 |
浅浅解释一下~~~还是小明与小芳
有连接: 小明给小芳打电话~~有连接,因为小芳需要接通
无连接: 小明给小芳发短信~~无连接,因为小芳不需要接通
可靠传输: 小明知道小芳接没接到电话
不可靠传输: 小明不知道小芳收没收到短信
面向字节流~数据报~: IO说过~
全双工: 同一时间,只能小明给小芳打电话,或者小芳给小明打电话~~
半双工: 同一时间,小明可以给小芳发消息, 小芳也可以给小明发消息~
3)代码UDP的socket 客户端-服务器 介绍&代码
i)要掌握的两个类: DatagramSocket, DatagramPacket
构造方法 | 方法 | |
DatagramSocket | DatagramSocket() 无参 一般用户客户端 | void receive(DatagramPacket p) 接收数据报 |
DatagramSocket(int port) 有参(端口号)一般用于服务器 | void send(DatagramPacket p) 发送数据报 | |
void close | ||
DatagramPacket | DatagramPacket(byte[]buf.int length) 构造一DatagramPacke接收数据报 | InetAddress 从接收(发送)的数据报中,获取发送(接收)端主机IP地址 |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造一DatagramPacke发送数据报 | int getPort() 从接收(发送)的数据报中,获取发送(接收)端主机的端口号 | |
byte[] getData() 获取数据报中的数据 |
没错! 你肯定看不懂这两个有什么区别~
来让我举个栗子, socket是菜鸟驿站,而你的packet就是包裹,你要去菜鸟驿站才能邮寄包裹~
ii)最简单UDP版本的客户端-服务器—回显服务器
(⊙﹏⊙)里面有一些注释,这个代码不详细说了, 但是便于理解,我还是 举栗子!!!!
那我再来带你们走一下流程吧~~~小明决定去找小芳~,他选了离小芳家很近的地方,开了一个菜鸟驿站~~~每天早早上班,晚晚收工, 这天,小芳来去快递,她告诉小明,她的取件码~小明立马去给她找包裹~~~找到之后,核实信息,给了小芳,小芳say,谢谢~小明把取件记录写上~ 然后???然后,两个人吃晚饭去了!!!!我在这里继续更博客…
Okk~~没错,你带入一下,这个代码其实就是这个流程~
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;// 服务器要绑定的端口public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}//启动服务器public void start() throws IOException {System.out.println("服务器启动~");// 循环一次,处理一个请求 true是因为,不知道什么时候会接收到请求while (true) {// 1. 读取请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//receive参数是输出型参数,所以构造一个空的DatagramPacket对象,读取出网卡的数据// DatagramPacket转为一个字符串,方便打印String request = new String(requestPacket.getData(),0,requestPacket.getLength());// 2. 根据请求计算响应String respOnse= process(request);// 3. 把响应写回客户端DatagramPacket respOnsePacket= new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());//response.getBytes().length要有--单位(字节);response.length--单位(字符)--都是应该还好ascii一样,但是有中文就bug了socket.send(responsePacket);// 4. 打印一个日志,记录一下服务器的情况 客户端的IP地址,客户端的端口号System.out.printf("[%s:%d] req:%s ; resp:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);// 可以随便绑一个server.start();}
}
import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP;private int serverPort;public UdpEchoClient(String serverIP, int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() throws IOException {Scanner scanner = new Scanner(System.in);while (true) {// 1.从控制台读取用户输入的内容System.out.print("-> ");String request = scanner.next();// 2.构造一个UDP请求, 发送给服务器DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(this.serverIP),this.serverPort);socket.send(requestPacket);// 3.从服务器读取 UDP响应数据,并解析DatagramPacket respOnsePacket= new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String respOnse= new String(responsePacket.getData(),0,responsePacket.getLength());// 4.把服务器的响应显示到控制台上System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);client.start();}
}
4)代码TCP的socket 客户端-服务器 介绍
i)要掌握的两个类: ServerSocket, Socket
构造方法 | 方法 | |
ServerSocket 服务器用-监听端口 | ServerSocket(int port) 绑定端口 | Socket accept() 接受客户端的连接 |
void close() | ||
Socket 服务器,客户端都可-传输数据 | Socket(String host, int port) 尝试和指定服务器建立连接 | InetAddress getInetAddress() 获取对方IP地址和端口 |
InputStream getInputStream() 返回输入流 | ||
OutputStream getOutputStream() 返回输出流 |
ii)补充知识点~长连接,短连接
短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是短连接只能一次收发数据
长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {ServerSocket listenSocket = null;public TcpEchoServer(int port) throws IOException {// listenSocket是去发宣传单的listenSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动~");ExecutorService service = Executors.newCachedThreadPool();while (true){// 1.先调用accept接受请求// 被宣传单吸引过来的,来给他进行详细产品介绍clientSocketSocket clientSocket = listenSocket.accept();// 2.处理连接//多线程
// Thread t = new Thread(()-> {
// try {
// processConnect(clientSocket);
// } catch (IOException e) {
// e.printStackTrace();
// }
// });
// t.start();//线程池service.submit(new Runnable() {@Overridepublic void run() {try {processConnect(clientSocket);} catch (IOException e) {e.printStackTrace();}}});}}private void processConnect(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 客户端上线了,建立连接成功 \n",clientSocket.getInetAddress().toString(),clientSocket.getPort());// 处理请求try (InputStream inputStream = clientSocket.getInputStream();//读OutputStream outputStream = clientSocket.getOutputStream()){ //写while (true) {// 1.读取请求&解析Scanner scanner = new Scanner(inputStream);if(!scanner.hasNext()){System.out.printf("[%s:%d] 客户端下线了,断开连接 ",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}String request = scanner.next();// 2.根据请求计算响应String respOnse= process(request);// 3.把响应写回给客户端PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req:%s resp:%s\n ",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);}} catch (IOException e) {e.printStackTrace();} finally {// 发一次广告,可能会来多个clientSocket, 那人都走了的时候,把不需要的clientSocket去除掉~~换个思路,去实习,活多的时候多找几个人,没活了在辞退掉~clientSocket.close();}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIp, int serverPort) throws IOException {socket = new Socket(serverIp,serverPort);}public void start(){Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {while (true){// 1.从控制台读取数据 构造请求System.out.print("-> ");String request = scanner.next();// 2.发送请求给服务器PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);printWriter.flush();// 3.从服务器上读取响应Scanner respOnseScanner= new Scanner(inputStream);String respOnse= responseScanner.next();// 4.打在控制台上System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);client.start();}
}
这个我更过啦~~~但是可以浅浅的拿出我的思维导图~
应用层:
传输层: TCP/UDP
网络层: