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

  • 相关阅读:
    cad怎么样创建动态块
    块定义从一个图形传到当前图形
    AutoCAD200X\Support\acad.lsp 启动时自动加载dll
    菜单变灰
    CAD实体双击弹出自定义窗体,可根据扩展数据(通用)
    转载:双击实体弹出对话框(重载AcDbDoubleClickEdit)
    当前已保存的用户坐标系坐标点到世界坐标系的转换
    Windows下编译PHP的C扩展
    flexpaper使用介绍
    IE6 png处理
  • 原文地址:https://www.cnblogs.com/YJK923/p/10173918.html
Copyright © 2020-2023  润新知