基础
- 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起
- 广域网WAN: 将远隔千里的计算机都连在一起;
- 为什么要分层?就是封装/隔离
- 七层:应用层(http) 表示层 会话层 传输层(tcp/ucp) 网络层 (ip) 数据链层 物理层
- 广播的特性:一台结点发送数据,所有结点都能收到
- 数据中带着名字的(MAC地址),只有MAC地址一样的结点才接受数据,其他结点把数据丢弃即可。
- 冲突率:冲突检测+冲突的避免
- 路由器是分割局域网的
- 数据的传输过程是不断地封装+解包,每经过一个局域网(路由器)源mac和目标mac都会进行变化。IP指导mac地址的变化。
- IP地址是在IP协议中, 用来标识网络中不同主机的地址;
- MAC地址用来识别数据链路层中相连的节点;
- 一个进程可以拥有多个端口号,一个端口号只能被一个进程占用。
- IP标识一台设备,port标识一个进程,ip+port标识网络上的唯一的一台设备的唯一进程。
- 五元组:protocol(tcp/udp) 源IP 源port 目的IP 目的port
TCP
传输层协议
有连接
可靠传输
面向字节流
- 如何写一个TCP服务器:
1.创建一个TCP socket并进行绑定
2.循环:
(1:等待客户端连接上来
(2:把该客户端的处理工作交给线程池去处理
package tcp;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket tcpServerSocket = new ServerSocket(8080);
Scanner scanner = new Scanner(System.in);
while (true) {
Socket clientSocket = tcpServerSocket.accept();
InetAddress clientAddress = clientSocket.getInetAddress();
int clientPort = clientSocket.getPort();
System.out.printf("有客户端连接上来 %s:%d%n",
clientAddress.getHostAddress(), clientPort);
// 获取 字节流
InputStream is = clientSocket.getInputStream();
// 字节流转换为字符流
InputStreamReader isReader = new InputStreamReader(is, "UTF-8");
// 字符流转换缓冲字符流
BufferedReader reader = new BufferedReader(isReader);
// 获取输出字节流
OutputStream os = clientSocket.getOutputStream();
PrintStream out = new PrintStream(os, true, "UTF-8");
String line = reader.readLine();
System.out.println("好友说: " + line);
System.out.print("请回复> ");
String response = scanner.nextLine();
out.println(response);
clientSocket.close();
}
}
}
package tcp;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
Socket tcpClientSocket = new Socket();
byte[] ipv4 = {(byte) 192, (byte) 168, (byte) 0, (byte) 196};
InetAddress serverAddress = InetAddress.getByAddress(ipv4);
SocketAddress serverSocketAddress
= new InetSocketAddress(serverAddress, 8080);
tcpClientSocket.connect(serverSocketAddress);
while (true) {
System.out.print("请输出> ");
String request = scanner.nextLine();
// 通过字节流直接写入请求
OutputStream os = tcpClientSocket.getOutputStream();
PrintStream out = new PrintStream(os, true, "UTF-8");
out.println(request);
out.flush();
// 通过字节流,直接读取数据
InputStream is = tcpClientSocket.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8")
);
String response = reader.readLine();
System.out.println(response);
}
}
}
-
线程处理流程
1.把输入流和输出流都转成合适的字符流
2.等待对方的输入,直到一个特殊字符位置(\r\n)
3.回复对方消息 -
如何写一个TCP
UDP
传输层协议
无连接
不可靠传输
面向数据报
- 如何写UDP服务器:
1.创建一个UDP socket
2. 循环:
1).等待对方发送UDP报文过来
2).回复对方一个UDP报文
package udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class Server {
public static void main(String[] args) throws IOException {
//1.新建一个DatagramSocket
//创建一个数据报套接字
DatagramSocket udpserversocket = new DatagramSocket(9898);
byte[] receivebuffer = new byte[1024];
//用来指定数据包内存空间的大小
DatagramPacket receivepacket = new DatagramPacket(receivebuffer, receivebuffer.length);
//2.等着客户端来撩
//从此套接字接受数据包
udpserversocket.receive(receivepacket);
/**
* InetAddress类的对象用于IP地址和域名
*/
InetAddress chilentAddess = receivepacket.getAddress();
System.out.printf("我从%s:%d收到了消息%n", chilentAddess.getAddress(), receivepacket.getLength());
System.out.printf("我一共收到了%d字节的数据", receivepacket.getLength());
String message = new String(
receivepacket.getData(),
0,
receivepacket.getLength(),
"UTF-8"
);
System.out.println(message);
udpserversocket.close();
}
}
如何写UDP客户端:
1.创建一个UDP socket
2. 循环:
1)往一个server端口发送UDP报文
2)等待对方回复
package tcp.http;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
Socket tcpClientSocket = new Socket();
byte[] ipv4 = { (byte)192, (byte)168, (byte)0, (byte)196 };
InetAddress serverAddress = InetAddress.getByAddress(ipv4);
SocketAddress serverSocketAddress
= new InetSocketAddress(serverAddress, 8080);
tcpClientSocket.connect(serverSocketAddress);
while (true) {
System.out.print("请输出> ");
String request = scanner.nextLine();
// 通过字节流直接写入请求
OutputStream os = tcpClientSocket.getOutputStream();
PrintStream out = new PrintStream(os, true, "UTF-8");
out.println(request);
out.flush();
// 通过字节流,直接读取数据
InputStream is = tcpClientSocket.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8")
);
String response = reader.readLine();
System.out.println(response);
}
}
}
Socket
内核和用户程序直接进行网络数据交互的接口,绑定一个五元组