局域网(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接受请求
// 被宣传单吸引过来的,来给他进行详细产品介绍clientSocket
Socket clientSocket = listenSocket.accept();
// 2.处理连接
//多线程
// Thread t = new Thread(()-> {
// try {
// processConnect(clientSocket);
// } catch (IOException e) {
// e.printStackTrace();
// }
// });
// t.start();
//线程池
service.submit(new Runnable() {
@Override
public 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
网络层: