目录
网络的七层模型
TCP/UDP区别
三次握手和四次挥手
三次握手
四次挥手
socket编程
socket实现客户端与服务端对话
实现互相连续聊天
UDP编程
UDP实现客户端,服务端聊天
总结
网络的七层模型
?
应用层
表示层
会话层
传输层
网络层
数据链路层物理层
?传输层协议:TCP UDP
应用层:HTTP协议
TCP/UDP区别
维度 | TCP | UDP |
---|
可靠性 | 可靠 | 不可靠 | 速度 | 稍慢 | 更快 | 通信方式 | 点对点 | 点对点、一对多、多对多 | 通信内容 | 字节码 | 数据报 | 应用场景 | 传输文件 | 聊天、视频、语音 |
三次握手和四次挥手
TCP 传输控制协议
分客户端和服务端,属于可靠协议,不会丢失数据
TCP连接需要通过三次握手机制在客户端和服务端建立起链接
三次握手
-
客户端发送信号量SYN=1 和序列号seq=J 给服务端,客户端进入SYN_SENT(信号发送状态),等待服务器回答 -
服务器收到客户端信号后,发送信号量SYN=1、ACK=1,应答值ack=J+1,新的序列号seq=K给客户端,服务器进入SYN_RCVD(收到信号)状态 -
客户端收到服务器的应答消息,发送ACK=1,和应答值ack=K+1给服务器,客户端和服务器都进入ESTABLISHED(连接建立)状态
四次挥手
客户端和服务端断开链接需要四次挥手机制断开连接
-
客户端发送信号量FIN M给服务器端,进入FIN_WAIT1状态 -
服务端收到后,返回ack M+1给客户端,进入CLOSE_WAIT状态 -
服务端在发送FIN N信号给客户端 -
客户端收到后,返回应答信号ACK=1 ack=N+1给服务端,连接关闭
socket编程
? ? ? ? socket(套接字),用于TCP/IP协议的网络编程机制
? ? ? ? ServerSocket 服务端 对本机的某个端口进行监听
????????????????创建
????????????????????????ServerSocket(int port) 参数是端口号
????????????????方法
? ? ? ????????????????? close()关闭
? ? ? ? ????????????????Socket accept() 接受客户端连接,会堵塞线程,直到连接到客户端
? ? ? ? Socket 客户端 代表客户端向服务端请求连接 发送网络通知
? ? ? ? ? ? ? ? 创建
? ? ? ? ? ? ? ? ? ? ? ? Socket(String ip,int port) ip地址 端口号
? ? ? ? ? ? ? ? 方法
????????????????????????
????????????????????????disconnect() 关闭
????????????????????????OutputStream getOutputStream() 获得输出流
????????????????????????InputStream getInputStream() 获得输入流
????????????????????????注意:IO流关闭后,socket会自动关闭
socket实现客户端与服务端对话
? ? ? ? ? 客户端:
????????
package htp;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Client {
public void send(String ip, int port, String msg) {
try (Socket socket = new Socket(ip, port)) {
try (ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) {
out.writeUTF(msg);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() throws IOException {
System.out.println("客户端启动了");
try(ServerSocket socket = new ServerSocket(8080)){
//接受消息
new Thread(()->{
while (true){
try {
Socket accept = null;
accept = socket.accept();
System.out.println("客户机连接了"+accept.getInetAddress());
ObjectInputStream input = new ObjectInputStream(accept.getInputStream());
String str = null;
System.out.println("接受到"+str);
str = input.readUTF();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
public static void main(String[] args) throws IOException {
Client client = new Client();
client.start();
client.send("192.168.1.124", 8888, "java真厉害");
}
}
服务端:
package htp;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static final int PART = 8080;
public void start() throws IOException {
System.out.println("服务器启动了");
try(ServerSocket socket = new ServerSocket(PART)){
//接受消息
new Thread(()->{
while (true){
try {
Socket accept = null;
accept = socket.accept();
System.out.println("客户机连接了"+accept.getInetAddress());
ObjectInputStream input = new ObjectInputStream(accept.getInputStream());
String str = null;
System.out.println("接受到"+str);
str = input.readUTF();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
public void send(String ip,int port,String msg){
try(Socket socket = new Socket(ip,port)){
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeUTF(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
Server server = new Server();
server.start();
server.send("192.168.1.124",8888,"我是服务器");
} catch (IOException e) {
e.printStackTrace();
}
}
}
实现互相连续聊天
? ? ? ? 创建输入流线程
package htp;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
public class ReaderRunnable implements Runnable{
private Socket socket;
public ReaderRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true){
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
String s = input.readUTF();
System.out.println("接收到了"+socket.getInetAddress()+"消息:"+s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建输出流线程
package htp;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;
public class WriterRunnable implements Runnable{
private Socket socket;
public WriterRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
Scanner scanner = new Scanner(System.in);
while (true){
try {
System.out.println("输入框:");
String msg = scanner.nextLine();
out.writeUTF(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
创建服务端
package htp;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatHome {
public void send(String ip,int port) throws IOException {
while (true){
ExecutorService executorService = Executors.newFixedThreadPool(2);
ServerSocket socket = new ServerSocket(port);
Socket accept = socket.accept();
executorService.execute(new ReaderRunnable(accept));
executorService.execute(new WriterRunnable(accept));
}
}
public static void main(String[] args) {
try {
new ChatHome().send("192.168.1.124",8888);
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建客户端
package htp;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatHome2 {
public void send(String ip,int port) throws IOException {
Socket socket = new Socket(ip,port);
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new ReaderRunnable(socket));
executorService.execute(new WriterRunnable(socket));
}
public static void main(String[] args) {
try {
new ChatHome2().send("192.168.1.120",8080);
} catch (IOException e) {
e.printStackTrace();
}
}
}
先启动服务端,再启动客户端,就可以实现相互聊天了。
UDP编程
数据报协议,类似广播,属于不可靠的协议,无连接
服务端
DatagramSocket(int port) 指定端口获得发送的数据报
客户端
DatagramSocket() 作为客户端使用
主要方法
receive(DatagramPacket) 接收数据包
send(DatagramPacket) 发送数据报
UDP实现客户端,服务端聊天
DatagramPacket 包
DatagramPacket(String ip,int port) 发送前指定ip和端口
public class UDPServer {
public static final int PORT = 8888;
public void start(){
System.out.println("启动服务");
//创建UDP服务端
try {
DatagramSocket server = new DatagramSocket(PORT);
//接收数据报
while(true) {
byte[] buff = new byte[1024];
DatagramPacket packet = new DatagramPacket(buff,0,buff.length);
//将接收的数据放入数据报
server.receive(packet);
String msg = new String(packet.getData(),0,packet.getLength(),"UTF-8");
System.out.println("接收到:" + msg);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new UDPServer().start();
}
}
public class UDPClient {
public void send(String ip,int port,String msg){
//创建客户端
try {
DatagramSocket client = new DatagramSocket();
//创建数据报
byte[] buff = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buff,0,buff.length, InetAddress.getByName(ip),port);
//发送数据报
client.send(packet);
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new UDPClient().send("127.0.0.1",8888,"Hello UDP!!");
}
}
?可以根据socket完成udp连续聊天。
总结
? ? ? ? 网络的七层模型
? ? ? ? TCP的三次握手和四次挥手
? ? ? ? SOCKET编程和UDP编程?
|