网络基础及TCP 协议 实现 Server/Client 简单通信 (socket 套接字)

前置知识:IO流 – 字节流和字符流的区别和使用,分别实现文本的复制

引言:

生活中的每个人都在进行网络通信(只要你不是八九十岁的老大爷老大妈,甚至有的老大妈大
爷比年轻人玩的还 6)。我们每天用的 QQ、微信 、and so on …实际上都是网络通信。

网络编程:

在这里插入图片描述
上图展现的就是一个简单的网络通信, 计算机 A 通过协议和传输到网络,网络再通过协议传输给另一个计算机。那什么是协议呢?

协议:为了让网络中不同计算机之间能够相互通信而建立的规则、约定、约定。
常见的协议有:

TCP协议:面向连接的、可靠的(不丢失、不重复、有序)、基于字节流的传输通信协议。

UDP协议:无连接的协议,在传输协议之前,客户端和服务端之间不建立和维护连接。提供不可靠的数据传输
ip地址:网络上的唯一标识。(就像我们的家庭地址一样)。

ip的组成: 32 位,由 4 个 8 位 2 进制组成。(每一位最大值是 255,每一位十进制表示 0 ~ 255)
二进制不容易记忆,所以改成 了十进制。

socket(套接字): 基于 TCP 协议的网络通信,可以提供双向安全连接的网络通信,
socket 需要借助数据流(字节流) 来完成数据的传递工作。
在这里插入图片描述

实现C/S通信的简单步骤:

1、建立连接(服务端准备服务,开放端口,客户端根据 ip 地址和端口号 找到 对应的计算机进行连接)

2、通过 socket 生成 inputStream/outputStream(准备发送数据)

3、通过 inputStream/outputStream 进行发送、接受数据

4、关闭相应的流

TCP 实现通信:

Server.java --服务端

package cs;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {


    public static void main(String[] args) {


        Socket socket = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader reader = null;
        try {
            // 准备服务(ip,端口),通过 serverSocket 产生服务端
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("服务端已连接");

            // 相当于是一个监听器,监听客户端的连接,只有监听到连接后 才会向下走
            socket = serverSocket.accept();
            System.out.println("连接成功。。。。。。。。。。。。。");

            // 通过 socket 只能得到字节流,要想用其他的流就需要进行转换
            // 现在接受信息,就是输入流(注意参照物)
            in = socket.getInputStream();

            // 将字节流转换为字符流,因为传过来的是字符,字符流在转化成缓存流(就不用再自己去弄缓存区了)
            reader = new BufferedReader(new InputStreamReader(in));

            // 存储信息
            String info = null;

            // 客户端发送的信息可能有多条,逐行读取
            while ((info = reader.readLine()) != null) {
                System.out.println("I am server,接受到客户端的信息是 :" + info);
            }

            // 将管道中的内容拿出来,不拿出来就还在管道中(输入流管道)
            socket.shutdownInput();

            // 反馈给客户端
            out = socket.getOutputStream();
            // 因为 out 是 字节流产生的对象,所以需要通过字节的方式进行传输
            out.write("Hello client,已经接受到你的消息!".getBytes());

            // 将管道中的内容拿出来(输出流管道)
            socket.shutdownOutput();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭各个流和套接字
                if (socket != null) socket.close();
                if (reader != null) reader.close();
                if (in != null) in.close();
                if (out != null) out.close();
            } catch (IOException E) {

                E.printStackTrace();
            }
        }


    }

}

Client.java – 客户端

package cs;


import java.io.*;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        BufferedReader reader = null;
        try {
            // 根据 ip 地址 和端口号建立连接
            socket = new Socket("127.0.0.1", 8888);
            // 输出流,向外发出信息
            out = socket.getOutputStream();
            // 通过字节的方式
            out.write("Hello Server".getBytes());
            // 将管道中的内容拿出来,不拿出来就还在管道中
            socket.shutdownOutput();

            // 输入流(服务端的信息输入到客户端)
            in = socket.getInputStream();

            // 字符转换流 --> 字符缓存流
            reader = new BufferedReader(new InputStreamReader(in));

            String info = null;

            while ((info = reader.readLine()) != null) {
                System.out.println(info);
            }

            socket.shutdownInput();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            try {
                if (socket != null) socket.close();
                if (reader != null) reader.close();
                if (in != null) in.close();
                if (out != null) out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


    }

}

效果图:

当只启动服务端时,由于没有客户端建立连接,所以服务端 serverSocket.accept(); 没有检测到有客户端连接,所以不会向下走:
在这里插入图片描述
当启动 客户端后:
在这里插入图片描述
在这里插入图片描述

后记:

到此,一个简单的网络通信就基本完成了,网络编程是一项大的内容,在Java 的学习过程中,只是简单的一部分,在上述代码的实现过程中,还用到了 IO 中的核心思想 – 装饰模式,有兴趣的小伙伴可以了解一下,由于博主能力有限,大家可以尝试着进行改进,实现聊天通讯,实现客户端和服务端的交互。相信有了上面的基础实现这个功能应该不难,后续我也会更新上。
有问题的小伙伴欢迎在下方留言。
如果感觉对您有帮助,别忘了点个小赞哦,嘻嘻,关注一下也是可以的,加油!!

猜你喜欢

转载自blog.csdn.net/qq_43619271/article/details/106307488