• Socket 编程之 TCP 实现


    前几天介绍了计算机网络的一些概念,并介绍了几个协议。下面就说说 Java 中的 Socket 编程,服务器和客户端是如何通信的呢?

    首先要介绍一下 Socket ,我们知道在 TCP/IP 协议簇中,TCP、UDP 协议都是在传输层,应用层基于传输层进行通信。而 Socket 可以看成是对 TCP 、UDP 协议的实现。具体到编程的时候,要看业务选择是使用 TCP 还是 UDP 协议。今天主要讲的就是基于 TCP 通信的 Socket 实现。若你对 TCP 还不熟悉。可以看这篇文章。

    Java 中为 TCP 协议提供了两个类:Socket 类和 ServerSocket 类。一个 Socket 实例代表了 TCP 连接的一个客户端,而一个 ServerSocket 实例代表了 TCP 连接的一个服务器端,一般在 TCP Socket 编程中,客户端有多个,而服务器端只有一个,客户端 TCP 向服务器端 TCP 发送连接请求,服务器端的 ServerSocket 实例则监听来自客户端的 TCP 连接请求,并为每个请求创建新的 Socket 实例,由于服务端在调用 accept()等待客户端的连接请求时会阻塞,直到收到客户端发送的连接请求才会继续往下执行代码,因此要为每个 Socket 连接开启一个线程(这里就是多线程的应用啊)。服务器端要同时处理 ServerSocket 实例和 Socket 实例,而客户端只需要使用 Socket 实例。

    另外,每个 Socket 实例会关联一个 InputStream 和 OutputStream 对象,我们通过将字节写入 Socket 的 OutputStream 来发送数据,并通过从 InputStream 来接收数据。

    好吧,上面的描述可能有点懵,下面就来看一个 demo。使用 Socket 实现一个简单的交互,在服务器端使用多线程来处理请求。

    客户端实现如下:

    public class Client {
        public static void main(String[] args) throws IOException {
            Socket socket = null;
            PrintWriter pw = null;
            BufferedReader br = null;
            try {
                // 创建Socket对象,指明需要连接的服务器地址和端口
                socket = new Socket("localhost", 6688);
    
                // 连接建立后,通过 Socket 输出流向服务器端发送请求信息 
                pw = new PrintWriter(socket.getOutputStream());
                pw.write("Hello , server . I'm Client !");
                pw.flush();
                socket.shutdownOutput();
    
                // 通过输入流获取服务器端返回的响应信息;
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String info = null;
                    while((info = br.readLine()) != null){
                        System.out.println("服务器返回信息: "+ info);
                }
                socket.shutdownInput();
    
            ----后面的错误处理和关闭资源省略-----
        }
    }
    

    服务器端实现如下:

    public class Server {
        public static void main(String[] args) throws IOException {
            Socket socket = null;
            try {
                // 创建ServerSocket对象,绑定监听端口
                ServerSocket serverSocket = new ServerSocket(6688);
                while(true){
                    // 通过accept()方法监听客户端请求
                    socket =serverSocket.accept();
                    ServerThread serverThread = new ServerThread(socket);
                    serverThread.start();
                }
        }
    }

    线程具体实现如下:

    public class ServerThread extends Thread {
        Socket socket = null;
        BufferedReader br = null;
        PrintWriter pw = null;
    
        public ServerThread(Socket socket){
            this.socket = socket;
        }
    
        @Override
        public void run() {
            try {
                // 连接建立后,通过输入流读取客户端发送的请求信息 msg
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                StringBuffer msg = new StringBuffer();
                String info = null;
                while((info = br.readLine()) != null){
                    msg.append(info);
                }
                System.out.println("服务器收到 [ "+ socket.getInetAddress()+" ] 的消息 [ " + msg+" ]");
                socket.shutdownInput();
    
                // 通过输出流向客户端发送相应信息
                pw = new PrintWriter(socket.getOutputStream());
                pw.write(" success !");
                pw.flush();
                socket.shutdownOutput();
            } 
        }
    }
    

    总结一下 Socket TCP 中实战的步骤。

    服务器端:

    (1) 创建ServerSocket对象,绑定监听端口;
    (2) 通过accept()方法监听客户端请求;
    (3) 连接建立后,通过输入流读取客户端发送的请求信息;
    (4) 通过输出流向客户端发送相应信息;

    (5) 关闭响应资源。

    客户端:

    (1) 创建Socket对象,指明需要连接的服务器地址和端口;
    (2) 连接建立后,通过输出流向服务器端发送请求信息;
    (3) 通过输入流获取服务器端返回的响应信息;

    (4) 关闭响应资源。

    注意:

    1 首先执行服务器端代码。

    2 服务器端执行之后默认就一直在等待客户端的连接请求。

    3 以上只是一个非常基础的案例,这只是 Socket 编程的冰山一角。

    4 可以优化的地方还有很多,服务器端参数的优化,如,接受数据的缓冲区大小、等待客户端连接的最长时间、使用线程池处理请求等。

  • 相关阅读:
    Convolutional Neural Network-week1编程题(一步步搭建CNN模型)
    Coursera Deep Learning笔记 卷积神经网络基础
    爬取b站周杰伦新歌mv弹幕 绘制词云
    Coursera Deep Learning笔记 结构化机器学习项目 (下)
    Golang-执行go get私有库提示”410 Gone“ 解决办法
    golang常用的http请求操作
    关于asyncio知识(四)
    关于asyncio知识(二)
    Python Every Class Needs a __repr__
    关于asyncio知识(一)
  • 原文地址:https://www.cnblogs.com/YJK923/p/10173918.html
Copyright © 2020-2023  润新知