IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Socket套接字实现一对一聊天 -> 正文阅读

[网络协议]Socket套接字实现一对一聊天

一 关于Socket

1.1 简介

Socket,又称套接字,在TCP/IP协议分层架构中,属应用层和传输层之间的一个抽象层(也有的说是属于传输层),它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。

在这里插入图片描述

1.2 优点

  1. 传输数据时间短,性能高
  2. 可以加密,数据安全性强
  3. 适合客户端和服务器端之间信息实时交互
  4. 传输数据为字节级,传输数据可自定义,数据量小

1.3 缺点

相对于http协议传输,增加了开发量

二 效果图展示

image-20220411231418077

image-20220411231435625

三 代码

3.1 服务端

package com.wyq;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.Scanner;

/**
 * @ClassName SocketServer
 * @Description: //TODO 服务端
 * @Author wyq
 * @Date 2022/4/11 20:39
 */
public class SocketServer {
    public static void main(String[] args) throws IOException {
        //创建Scanner对象,接收键盘输入
        Scanner input = new Scanner(System.in);
        //创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(8888);
        //等待客户端连接
        System.out.println("等待客户端连接。。。");
        //监听客户端连接,返回Socket对象
        Socket socket = serverSocket.accept();
        //获得当前客户端的IP地址
        String clientIP = socket.getInetAddress().getHostAddress();
        System.out.println("【" + clientIP + "】连接成功..." + new Date());
        //通过Socket对象获得InputStream和OutputStream
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        // 借助于 InputStream 和 OutputStream 获得 BufferedReader 和 BufferedWriter
        InputStreamReader isr = new InputStreamReader(in);
        BufferedReader reader = new BufferedReader(isr);
        OutputStreamWriter osw = new OutputStreamWriter(out);
        BufferedWriter writer = new BufferedWriter(osw);

        // 通过 BufferedWriter 向客户端发送连接成功信息
        writer.write("服务端连接成功..." + new Date());
        writer.newLine();
        //强制把数据输出,清空缓冲区
        writer.flush();

        while (true) {
            // 接收来自客户端的信息
            System.out.println("来自【客户端】的信息 (" + new Date() + ") :" + reader.readLine());
            // 通过控制台输入信息并且进行发送
            writer.write(input.next());
            writer.newLine();
            writer.flush();
        }
    }
}

3.2 客户端

package com.wyq;

import java.io.*;
import java.net.Socket;
import java.util.Date;
import java.util.Scanner;

/**
 * @ClassName SocketClient
 * @Description: //TODO 客户端
 * @Author wyq
 * @Date 2022/4/11 21:09
 */
public class SocketClient {
    public static void main(String[] args) throws IOException {
        // 创建 Scanner 对象
        Scanner input = new Scanner(System.in);
        // 创建 Socket 对象
        Socket socket = new Socket("127.0.0.1", 8888);
        // 通过 Socket 对象获得 InputStream 和 OutputStream
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        // 借助于 InputStream 和 OutputStream 获得 BufferedReader 和 BufferedWriter
        InputStreamReader isr = new InputStreamReader(in);
        BufferedReader reader = new BufferedReader(isr);
        OutputStreamWriter osw = new OutputStreamWriter(out);
        BufferedWriter writer = new BufferedWriter(osw);

        while (true) {
            // 接收来自服务端的信息
            System.out.println("来自【服务端】的信息 (" + new Date() + ") :" + reader.readLine());
            // 通过控制台输入信息并且进行发送
            writer.write(input.next());
            writer.newLine();
            writer.flush();
        }
    }
}

四 通讯连接过程(源码解析)

在这里插入图片描述

4.1 服务端

  1. 创建Socket,bind()绑定地址,listen()监听套接字

    ServerSocket只需要一行代码就可以完成创建、绑定、监听Socket,绑定的地址没填默认就是本机的ip(在源码中InetAddress.anyLocalAddress()方法得出的结论),监听Socket监听的是改Socket的最大连接数,如果队列满时,会出现提示,并拒绝连接(源码的listen(int backlog)方法这样解释)。

    ServerSocket serverSocket = new ServerSocket(端口号);
    
  2. accept()监听连接

    accept()方法侦听要与ServerSocket建立的连接并接受它。该方法会阻塞,直到建立连接。

    Socket socket = serverSocket.accept();
    
  3. read()读数据

    accept()方法连接成功,会返回Socket对象,通过这一个对象,我们可以实现与客户端的互动,互动的过程涉及到对Socket的writeread,还是建议创建一个线程池,在线程中对Socket的writeread进行操作。

            //通过Socket对象获得InputStream和OutputStream
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();
            // 借助于 InputStream 和 OutputStream 获得 BufferedReader 和 BufferedWriter
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader reader = new BufferedReader(isr);
            OutputStreamWriter osw = new OutputStreamWriter(out);
            BufferedWriter writer = new BufferedWriter(osw);
    
            while (true) {
                // 接收来自客户端的信息
                System.out.println(reader.readLine());
                // 通过控制台输入信息并且进行发送
                writer.write(input.next());
                writer.newLine();
                writer.flush();
            }
    

    在上面的代码中,使用while开启一个死循环,这时候可千万不要理解为这串代码一直在执行着while循环,readLine()方法里,有一个地方会执行到一个read(char cbuf[], int off, int len)方法,源码是这样介绍这个方法的:

    Reads characters into a portion of an array. This method will block until some input is available, an I/O error occurs, or the end of the stream is reached
    将字符读入数组的一部分。此方法将阻塞,直到某些输入可用、发生 IO 错误或到达流末尾

    因此,readLine()没有接收到字符,会被readLine()方法里面的read(char cbuf[], int off, int len)方法阻塞,直到接收到字符,继续往下执行,执行完,重新开始while循环。

  4. write()写数据

    flush()方法才可实现推送消息给客户端。

    // 通过控制台输入信息并且进行发送
    writer.write(input.next());
    writer.newLine();
    //强制把数据输出,清空缓冲区
    writer.flush();
    
  5. close()关闭连接

    关闭连接,也要顺带把与用户的Socket连接也给关闭掉

    // 方法一:
    socket.close(); // 关闭指定客户端的连接
    reader.close(); // 关闭阅读器
    server.close(); // 关闭ServerSocket
    // 方法二:
    // 接收客户端的消息,如果消息为约定好的断开连接的消息,则断开连接
    

4.2 客户端

  1. 创建Socket、connect()连接Socket

    客户端创建Socket,new Socket(String host, int port);需要抛出异常,当IP地址错误、端口号错误、服务器ServerSocket未启动时,都会抛出异常,即连接失败。

    try {
    	Socket socket = new Socket(String host, int port);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
  2. write()写数据

    同服务端

  3. read()读数据

    同服务端

  4. close()关闭连接

    // 方法一:
    socket.close();
    // 方法二:
    // 给服务器发送相关消息,由服务器断开与指定客户端的连接
    
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:40:35  更:2022-04-15 00:42:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:44:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码