快速了解网络通信,实现客户端和服务端聊天

目录

网络的七层模型

TCP/UDP区别

三次握手和四次挥手

三次握手

四次挥手

socket编程

socket实现客户端与服务端对话

实现互相连续聊天

UDP编程

UDP实现客户端,服务端聊天

总结


网络的七层模型

 

应用层

表示层

会话层

传输层

网络层

数据链路层物理层

 传输层协议:TCP UDP

应用层:HTTP协议

TCP/UDP区别

维度TCPUDP
可靠性可靠不可靠
速度稍慢更快
通信方式点对点点对点、一对多、多对多
通信内容字节码数据报
应用场景传输文件聊天、视频、语音

三次握手和四次挥手

TCP 传输控制协议

分客户端和服务端,属于可靠协议,不会丢失数据

TCP连接需要通过三次握手机制在客户端和服务端建立起链接

三次握手

  1. 客户端发送信号量SYN=1 和序列号seq=J 给服务端,客户端进入SYN_SENT(信号发送状态),等待服务器回答

  2. 服务器收到客户端信号后,发送信号量SYN=1、ACK=1,应答值ack=J+1,新的序列号seq=K给客户端,服务器进入SYN_RCVD(收到信号)状态

  3. 客户端收到服务器的应答消息,发送ACK=1,和应答值ack=K+1给服务器,客户端和服务器都进入ESTABLISHED(连接建立)状态

四次挥手

客户端和服务端断开链接需要四次挥手机制断开连接

  1. 客户端发送信号量FIN M给服务器端,进入FIN_WAIT1状态

  2. 服务端收到后,返回ack M+1给客户端,进入CLOSE_WAIT状态

  3. 服务端在发送FIN N信号给客户端

  4. 客户端收到后,返回应答信号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编程 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值