zoukankan      html  css  js  c++  java
  • JAVA-TCP

     

     TCP的机制:

     

     TCP链接、传输过程。

    TCP能做什么:

    1、聊天消息传输.

    2、单人语音、视频等

    限制:无法进行广播、多播操作.

    核心API:

     

     

     

     

     

    客户端:

     

     服务端:

     

     四次挥手:

     传输可靠性:

    排序、顺序发送、顺序组装

    丢弃、超时

    重发机制、定时器

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.*;
    import java.nio.ByteBuffer;
    
    public class TcpClient {
        private static final int PORT = 20000;
        private static final int LOCAL_PORT = 20001;
    
        public static void main(String[] args) throws IOException {
            Socket socket = createSocket();
    
            initSocket(socket);
    
            // 链接到本地20000端口,超时时间3秒,超过则抛出超时异常
            socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 3000);
    
            System.out.println("已发起服务器连接,并进入后续流程~");
            System.out.println("客户端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());
            System.out.println("服务器信息:" + socket.getInetAddress() + " P:" + socket.getPort());
    
            try {
                // 发送接收数据
                todo(socket);
            } catch (Exception e) {
                System.out.println("异常关闭");
            }
    
            // 释放资源
            socket.close();
            System.out.println("客户端已退出~");
    
        }
    
        private static Socket createSocket() throws IOException {
            /*
            // 无代理模式,等效于空构造函数
            Socket socket = new Socket(Proxy.NO_PROXY);
    
            // 新建一份具有HTTP代理的套接字,传输数据将通过www.baidu.com:8080端口转发
            Proxy proxy = new Proxy(Proxy.Type.HTTP,
                    new InetSocketAddress(Inet4Address.getByName("www.baidu.com"), 8800));
            socket = new Socket(proxy);
    
            // 新建一个套接字,并且直接链接到本地20000的服务器上
            socket = new Socket("localhost", PORT);
    
            // 新建一个套接字,并且直接链接到本地20000的服务器上
            socket = new Socket(Inet4Address.getLocalHost(), PORT);
    
            // 新建一个套接字,并且直接链接到本地20000的服务器上,并且绑定到本地20001端口上
            socket = new Socket("localhost", PORT, Inet4Address.getLocalHost(), LOCAL_PORT);
            socket = new Socket(Inet4Address.getLocalHost(), PORT, Inet4Address.getLocalHost(), LOCAL_PORT);
            */
    
            Socket socket = new Socket();
            // 绑定到本地20001端口
            socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), LOCAL_PORT));
    
            return socket;
        }
    
        private static void initSocket(Socket socket) throws SocketException {
            // 设置读取超时时间为2秒
            socket.setSoTimeout(2000);
    
            // 是否复用未完全关闭的Socket地址,对于指定bind操作后的套接字有效
            socket.setReuseAddress(true);
    
            // 是否开启Nagle算法
            socket.setTcpNoDelay(true);
    
            // 是否需要在长时无数据响应时发送确认数据(类似心跳包),时间大约为2小时
            socket.setKeepAlive(true);
    
            // 对于close关闭操作行为进行怎样的处理;默认为false,0
            // false、0:默认情况,关闭时立即返回,底层系统接管输出流,将缓冲区内的数据发送完成
            // true、0:关闭时立即返回,缓冲区数据抛弃,直接发送RST结束命令到对方,并无需经过2MSL等待
            // true、200:关闭时最长阻塞200毫秒,随后按第二情况处理
            socket.setSoLinger(true, 20);
    
            // 是否让紧急数据内敛,默认false;紧急数据通过 socket.sendUrgentData(1);发送
            socket.setOOBInline(true);
    
            // 设置接收发送缓冲器大小
            socket.setReceiveBufferSize(64 * 1024 * 1024);
            socket.setSendBufferSize(64 * 1024 * 1024);
    
            // 设置性能参数:短链接,延迟,带宽的相对重要性
            socket.setPerformancePreferences(1, 1, 0);
        }
    
        private static void todo(Socket client) throws IOException {
            // 得到Socket输出流
            OutputStream outputStream = client.getOutputStream();
    
    
            // 得到Socket输入流
            InputStream inputStream = client.getInputStream();
            byte[] buffer = new byte[256];
            ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
    
            // byte
            byteBuffer.put((byte) 126);
    
            // char
            char c = 'a';
            byteBuffer.putChar(c);
    
            // int
            int i = 2323123;
            byteBuffer.putInt(i);
    
            // bool
            boolean b = true;
            byteBuffer.put(b ? (byte) 1 : (byte) 0);
    
            // Long
            long l = 298789739;
            byteBuffer.putLong(l);
    
    
            // float
            float f = 12.345f;
            byteBuffer.putFloat(f);
    
    
            // double
            double d = 13.31241248782973;
            byteBuffer.putDouble(d);
    
            // String
            String str = "Hello你好!";
            byteBuffer.put(str.getBytes());
    
            // 发送到服务器
            outputStream.write(buffer, 0, byteBuffer.position() + 1);
    
            // 接收服务器返回
            int read = inputStream.read(buffer);
            System.out.println("收到数量:" + read);
    
            // 资源释放
            outputStream.close();
            inputStream.close();
        }
    }
    

      

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Inet4Address;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    
    
    public class TcpServer {
        private static final int PORT = 20000;
    
        public static void main(String[] args) throws IOException {
            ServerSocket server = createServerSocket();
    
            initServerSocket(server);
    
            // 绑定到本地端口上
            server.bind(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 50);
    
    
            System.out.println("服务器准备就绪~");
            System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());
    
    
            // 等待客户端连接
            for (; ; ) {
                // 得到客户端
                Socket client = server.accept();
                // 客户端构建异步线程
                ClientHandler clientHandler = new ClientHandler(client);
                // 启动线程
                clientHandler.start();
            }
    
        }
    
        private static ServerSocket createServerSocket() throws IOException {
            // 创建基础的ServerSocket
            ServerSocket serverSocket = new ServerSocket();
    
            // 绑定到本地端口20000上,并且设置当前可允许等待链接的队列为50个
            //serverSocket = new ServerSocket(PORT);
    
            // 等效于上面的方案,队列设置为50个
            //serverSocket = new ServerSocket(PORT, 50);
    
            // 与上面等同
            // serverSocket = new ServerSocket(PORT, 50, Inet4Address.getLocalHost());
    
            return serverSocket;
        }
    
        private static void initServerSocket(ServerSocket serverSocket) throws IOException {
            // 是否复用未完全关闭的地址端口
            serverSocket.setReuseAddress(true);
    
            // 等效Socket#setReceiveBufferSize
            serverSocket.setReceiveBufferSize(64 * 1024 * 1024);
    
            // 设置serverSocket#accept超时时间
            // serverSocket.setSoTimeout(2000);
    
            // 设置性能参数:短链接,延迟,带宽的相对重要性
            serverSocket.setPerformancePreferences(1, 1, 1);
        }
    
        /**
         * 客户端消息处理
         */
        private static class ClientHandler extends Thread {
            private Socket socket;
    
            ClientHandler(Socket socket) {
                this.socket = socket;
            }
    
            @Override
            public void run() {
                super.run();
                System.out.println("新客户端连接:" + socket.getInetAddress() +
                        " P:" + socket.getPort());
    
                try {
                    // 得到套接字流
                    OutputStream outputStream = socket.getOutputStream();
                    InputStream inputStream = socket.getInputStream();
    
                    byte[] buffer = new byte[256];
                    int readCount = inputStream.read(buffer);
                    ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);
    
                    // byte
                    byte be = byteBuffer.get();
    
                    // char
                    char c = byteBuffer.getChar();
    
                    // int
                    int i = byteBuffer.getInt();
    
                    // bool
                    boolean b = byteBuffer.get() == 1;
    
                    // Long
                    long l = byteBuffer.getLong();
    
                    // float
                    float f = byteBuffer.getFloat();
    
                    // double
                    double d = byteBuffer.getDouble();
    
                    // String
                    int pos = byteBuffer.position();
                    String str = new String(buffer, pos, readCount - pos - 1);
    
                    System.out.println("收到数量:" + readCount + " 数据:"
                            + be + "
    "
                            + c + "
    "
                            + i + "
    "
                            + b + "
    "
                            + l + "
    "
                            + f + "
    "
                            + d + "
    "
                            + str + "
    ");
    
                    outputStream.write(buffer, 0, readCount);
                    outputStream.close();
                    inputStream.close();
    
                } catch (Exception e) {
                    System.out.println("连接异常断开");
                } finally {
                    // 连接关闭
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                System.out.println("客户端已退出:" + socket.getInetAddress() +
                        " P:" + socket.getPort());
    
            }
        }
    }
    

      

  • 相关阅读:
    Vue 兄弟组件通信(不使用Vuex)
    vue2.0 #$emit,$on的使用
    Bootstrap栅格系统基本使用
    字体图标使用
    js事件委托
    帆布小球碰壁效果
    vuex -- vue的状态管理模式
    JavaScript --经典问题
    总结获取原生JS(javascript)基本操作
    git的基本操作
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/12153475.html
Copyright © 2011-2022 走看看