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类关于TCP字符流编程的理解学习 -> 正文阅读

[网络协议]Socket类关于TCP字符流编程的理解学习

作者:token keyword

基本介绍

套接字(socket):是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口

  1. socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。
  2. socket简单的说,由 端口,协议,地址三个组成部分。
  3. 套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
  4. 由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。
  5. 但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
  • Socket主要用于开发网络应用程序,其背广泛采用

  • 通信的两端都需要有Socket,是两台机器间通信的断点

  • 网络通信其实就是Socket的通信

  • Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输

  • 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端

示意图:

image-20220727232736510

代码实现

一定要注意,必须要先开启服务端,在启动客户端,否则会报错

**注意:**这里的代码示例都是关于发送与接收信息,如果需要发送或接收图片等都差不多,只是必须要使用字节流而不能使用字符流,基本流程都是使用IO中的知识。

需求1:

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务器,发送"hello,server",退出
  4. 服务端接收到客户端发送的信息并输出,退出

服务端

/**
 *
 * 服务端
 * 需求:接收从客户端发来的信息并输出
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP01Server {
    public static void main(String[] args) throws IOException {

        //新建serverSocket对象,实现9999端口监听
        ServerSocket serverSocket = new ServerSocket(9999);

        //客户端连接后会生成管道
        Socket socket = serverSocket.accept();

        //获取管道的输入流
        InputStream inputStream = socket.getInputStream();
        byte[] buf=new byte[1024];
        int len = 0;

        while ((len = inputStream.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }

        //关闭流
        inputStream.close();
        socket.close();
        serverSocket.close();


    }
}

客户端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 客户端
 * 需求:向服务器端发送一条信息
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP01Client {
    public static void main(String[] args) throws IOException {
        //获取socket连接
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        //获取输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //往输出流中写入信息
        outputStream.write("hello,server".getBytes());

        //关闭流
        outputStream.close();
        socket.close();
    }
}

测试结果

服务端收到信息

image-20220727231736859

需求2

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务器,发送"hello,server",并接收服务端回发的"hello,client",退出
  4. 服务端接收到客户端发送的信息输出,并发送"hello,client",退出

服务端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 服务端
 * 需求:接收从客户端发来的信息输出,并返回一条消息给客户端
 *
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP02Server {
    public static void main(String[] args) throws IOException {

        //新建serverSocket对象,实现9999端口监听
        ServerSocket serverSocket = new ServerSocket(9999);

        //客户端连接后会生成管道
        Socket socket = serverSocket.accept();

        //获取管道的输入流,获取客户端发来的信息
        InputStream inputStream = socket.getInputStream();
        byte[] buf=new byte[1024];
        int len = 0;

        while ((len = inputStream.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }
        //关闭读取
        socket.shutdownInput();

        //获取输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //往输出流中写入信息,发送给服务端
        outputStream.write("hello,client".getBytes());
        //关闭写入
        socket.shutdownOutput();

        //关闭流
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();


    }
}

客户端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 客户端
 * 需求:向服务器端发送一条信息,并接收从服务器端返回的一条信息
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP02Client {
    public static void main(String[] args) throws IOException {
        //获取socket连接
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        //获取输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //往输出流中写入信息,发送给服务端
        outputStream.write("hello,server".getBytes());
        //关闭写入
        socket.shutdownOutput();

        //获取管道的输入流,获取服务器端发来的信息
        InputStream inputStream = socket.getInputStream();
        byte[] buf=new byte[1024];
        int len = 0;

        while ((len = inputStream.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }

        //关闭流
        inputStream.close();
        outputStream.close();
        socket.close();
    }
}

测试结果

服务端收到信息

image-20220727231852931

客户端收到信息

image-20220727231909658

需求3

使用字符流完成,之前两个需求都是使用的字节流去完成

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务器,发送"hello,server",并接收服务端回发的"hello,client",退出
  4. 服务端接收到客户端发送的信息输出,并发送"hello,client",退出

服务端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 服务端
 * 需求:使用字符流,接收从客户端发来的信息输出,并返回一条消息给客户端
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP03Server {
    public static void main(String[] args) throws IOException {

        //新建serverSocket对象,实现9999端口监听
        ServerSocket serverSocket = new ServerSocket(9999);

        //客户端连接后会生成管道
        Socket socket = serverSocket.accept();

        //获取管道的输入流,获取客户端发来的信息
        InputStream inputStream = socket.getInputStream();
        //将字节流输入流转为字符流输入流
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        char[] cbuf=new char[1024];
        int len;
        while ((len = inputStreamReader.read(cbuf))!=-1){
            System.out.println(new String(cbuf,0,len));
        }
        //关闭读取
        socket.shutdownInput();

        //获取输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //将字节流输出流转换为字符流输出流
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
        //往输出流中写入信息,发送给服务端
        outputStreamWriter.write("hello,client");
        //需要刷新流后才能写入
        outputStreamWriter.flush();
        //关闭写入
        socket.shutdownOutput();

        //关闭流
        outputStreamWriter.close();
        inputStreamReader.close();
        socket.close();
        serverSocket.close();


    }
}

客户端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 客户端
 * 需求:使用字符流,向服务器端发送一条信息,并接收从服务器端返回的一条信息
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class ScoketTCP03Client {
    public static void main(String[] args) throws IOException {
        //获取socket连接
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        //获取输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //将字节流输出流转换为字符流输出流
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
        //往输出流中写入信息,发送给服务端
        outputStreamWriter.write("hello,server");
        //需要刷新流后才能写入
        outputStreamWriter.flush();

        //关闭写入
        socket.shutdownOutput();

        //获取管道的输入流,获取服务器端发来的信息
        InputStream inputStream = socket.getInputStream();
        //将字节流输入流转为字符流输入流
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        char[] cbuf=new char[1024];
        int len;
        while ((len = inputStreamReader.read(cbuf))!=-1){
            System.out.println(new String(cbuf,0,len));
        }

        //关闭流
        inputStreamReader.close();
        outputStreamWriter.close();
        socket.close();
    }
}

测试结果

服务端收到信息

image-20220727231959710

客户端收到信息

image-20220727231954226

发送图片、视频等文件流程说明

由于是图片、视频等文件,所以一定要使用字节流去进行传输

需求:

  1. 编写一个服务端和一个客户端
  2. 服务端在8888端口监听
  3. 客户端连接到服务端,发送本地一张图片
  4. 服务端接收到客户端发送的图片,保存到src下,发送“收到图片”给客户端,然后退出
  5. 客户端接收服务端发送的“收到图片”,然后退出

流程示例:

  1. 客户端使用字节输入流将磁盘中的图片输入到内存中
  2. 客户端使用字节输出流将内存中的图片输出给服务端
  3. 服务端使用字节输入流将客户端字节输出流中的图片获取得到
  4. 服务端使用字节输出流将图片输出到磁盘文件中

服务端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 服务端
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class TCPFileUploadServer {
    public static void main(String[] args) throws IOException {

        //监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        //等待连接
        Socket socket = serverSocket.accept();

        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        //创建的字节流输出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("basic_review\\src\\socket_\\图片.jpg"));
        //读取图片信息
        byte[] buf = new byte[1024];
        int len;
        while ((len = bufferedInputStream.read(buf)) != -1){

            bufferedOutputStream.write(buf,0,len);
        }
        bufferedOutputStream.flush();

        socket.shutdownInput();



        bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());

        bufferedOutputStream.write("收到图片".getBytes());

        //刷新流
        bufferedOutputStream.flush();

        socket.shutdownOutput();

        bufferedOutputStream.close();
        bufferedInputStream.close();
        socket.close();
        serverSocket.close();

    }
}

客户端

输出流写入数据后一定要进行flush(),同时进行结束标记

/**
 *
 * 客户端
 *
 * @author:雷子杰
 * @date:2022/7/27
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws IOException {
        //连接主机的8888端口,得到socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        //读取的文件地址
        String filePath ="f:\\ssm博客系统.jpg";
        //创建的字节流输入流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
        //创建的字节流输出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
        //读取图片信息
        byte[] buf = new byte[1024];
        int len;
        while ((len = bufferedInputStream.read(buf)) != -1){
            //写入到管道中
            bufferedOutputStream.write(buf,0,len);
        }
        //刷新流
        bufferedOutputStream.flush();
        //关闭写出
        socket.shutdownOutput();


        bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        while ((len = bufferedInputStream.read(buf)) != -1){
            System.out.println(new String(buf,0,len));

        }

        socket.shutdownInput();

        bufferedOutputStream.close();
        bufferedInputStream.close();

        socket.close();


    }
}

总结

目前复习java基础复习到了计算机网络阶段,发现自身在网络通信编程这方面的知识较为匮乏,本篇文章用于记载学习java网络编程技术

另外一个重点!!!!!在使用输出流写入数据后一定要进行flush(),同时进行结束标记,否则可能会报错

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 11:14:36  更:2022-08-06 11:16:19 
 
开发: 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/25 23:39:36-

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