• 网络编程基础


    基础知识

    客户端:指浏览器或者自定义的客户端。

    服务端:像Tomcat服务器或者自定义客户端。

    image.png
    image.png

    image.png
    image.png

    TCP/IP

    TCP:传输层协议。

    IP:网络层协议。

    TCP/IP.png

    TCP/UDP

    TCP与UDP区别

    TCP使用案例:用于RPC接口调用,发送电子邮件等需要可靠性传输的事情。

    UDP使用案例:用于视频这类的传输。

    相同点:

    • TCP与UDP都是网络层的通信协议,只是通信的协议不同。

    不同点:

    • TCP协议在通信前要先通过三次握手的方式建立连接,保证通信的可靠性。而UDP不需要建立连接接可以发送数据包,因此接收方不一定能收到,因此是不可靠的。
    • TCP协议需要建立连接和释放连接,因此传输效率低。而UDP不需要释放资源,因此开销小,速度快。
    • UDP可以进行广播发送,而TCP是点对点通信。
    • TCP在建立连接后可以进行大数据量的传输,而UDP会限制每个数据包的传输大小在64K以内。

    TCP/UDP.png

    TCP

    socket.png
    socket2.png
    socket3.png

    三次握手

    客户端建立连接请求时的三次握手:

    第一次握手:客户端向服务端发送syn报文和序号x;

    第二次握手:服务端接收到客户端的请求,发送ack=x+1报文,并发送序号y,syn报文。

    第三次握手:客户端接收到服务端的请求,发送ack= y+1报文,并发送序号z。

    为什么是三次握手而不是二次或者四次五次呢?

    因此根据三次握手我们客户端和服务端都可以知道自己发送正常,对方接收正常;而二次握手的话,服务端并不知道自己发送正常,只能知道客户端发送接收正常,自己接收正常,而不知道自己发送正常。而三次握手刚好就满足了这个条件。既然三次握手就满足了,四次五次就会显得多余了,虽然更多次的握手可以更加保证通信的正常,但是正常来说三次握手就能保证通信99%是可靠的,再多次的握手可靠性的提高并不高,意义不大。

    三次握手.png

    四次挥手

    客户端服务端都可以通过四次挥手关闭连接,但一般都是客户端发起四次挥手请求来关闭连接,因为我们服务端一般是24小时在线服务的。

    以客户端发起断开连接为例:

    客户端告诉服务端我要断开连接了。

    服务端相应客户端说我收到你的断开连接请求了。

    服务端断开连接,并发送请求告诉客户端我和你断开连接了。

    客户端收到断开连接请求断开了连接,并发送确认断开的请求告诉服务我和你断开连接了,这时候服务端就接收不到客户端的请求了,如果接收到了就表示没有真正断开连接。

    四次挥手.png

    示例小结

    public class TCPTest {
        /**
         * 客户端
         */
        @Test
        public void client() throws IOException {
            Socket socket = null;
            OutputStream os = null;
            try {
                InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
                //1创建Socke连接对象,指明要连接的服务端的ip和端口号
                socket = new Socket(inetAddress, 9000);
                //2获取输出流,用于输出数据
                os = socket.getOutputStream();
                //3写数据
                os.write("我叫客户端,你好啊".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4关闭流资源
                if (os != null) {
                    os.close();
                }
                if (socket != null) {
                    socket.close();
                }
            }
        }
    
        @Test
        public void server() throws IOException {
            InputStream is = null;
            ByteArrayOutputStream baos = null;
            ServerSocket serverSocket = null;
            Socket socket = null;
            try {
                //创建服务端的ServerSocket,指明自己的端口号,给客户端通过指定的ip和该端口号确定进程进行连接
                serverSocket = new ServerSocket(9000);
                //accept()用于接收来自客户端的连接
                socket = serverSocket.accept();
                //获取输入流
                is = socket.getInputStream();
                //读取输入流中的数据,ByteArrayOutputStream该流维护动态数组保存写入的数据
                baos = new ByteArrayOutputStream();
                byte[] buff = new byte[1024];
                int len;
                while ((len = is.read(buff)) != -1) {
                    baos.write(buff, 0, len);
                }
                System.out.println(baos.toString());
                System.out.println("收到客户端请求了!");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭资源
                baos.close();
                is.close();
                socket.close();
                serverSocket.close();
            }
        }
        /**
         * 我叫客户端,你好啊
         * 收到客户端请求了!
         */
    }
    

    示例小结——TCP发送接收文件

    public class TCPFileTest {
        /**
         * 客户端给服务端发生文件
         */
        @Test
        public void client() throws IOException {
            Socket socket = null;
            OutputStream os = null;
            FileInputStream fis = null;
            ByteArrayOutputStream baos = null;
            try {
                InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
                //1创建Socke连接对象,指明要连接的服务端的ip和端口号
                socket = new Socket(inetAddress, 9000);
                //2获取输出流,用于输出数据
                os = socket.getOutputStream();
                fis = new FileInputStream("是大臣.jpg");
                //3写数据
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, len);
                }
                System.out.println("向服务端发送图片成功!");
                //关闭数据的输出,不然服务端会一直阻塞着接收不往下走
                socket.shutdownOutput();
                //接收服务端的应答
                InputStream is = socket.getInputStream();
                baos = new ByteArrayOutputStream();
                byte[] buff = new byte[1024];
                int length;
                while ((length = is.read(buff)) != -1) {
                    baos.write(buff, 0, length);
                }
                System.out.println(baos.toString());
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4关闭流资源
                if (os != null) {
                    os.close();
                }
                if (socket != null) {
                    socket.close();
                }
            }
        }
        /**
         * 向服务端发送图片成功!
         * 客户端,你的文件收到了
         */
    
        /**
         * 服务端接收文件保存到本地
         *
         * @throws IOException
         */
        @Test
        public void server() throws IOException {
            InputStream is = null;
            FileOutputStream fos = null;
            ServerSocket serverSocket = null;
            Socket socket = null;
            OutputStream os = null;
            try {
                //创建服务端的ServerSocket,指明自己的端口号,给客户端通过指定的ip和该端口号确定进程进行连接
                serverSocket = new ServerSocket(9000);
                //accept()用于接收来自客户端的连接
                socket = serverSocket.accept();
                //获取输入流
                is = socket.getInputStream();
                //打开输出流写文件
                fos = new FileOutputStream("是大臣-copy5.jpg");
                byte[] buff = new byte[1024];
                int len;
                while ((len = is.read(buff)) != -1) {
                    fos.write(buff, 0, len);
                }
                System.out.println("收到客户端请求了!");
                //给客户端写出应答
                os = socket.getOutputStream();
                os.write("客户端,你的文件收到了".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭资源
                fos.close();
                is.close();
                socket.close();
                serverSocket.close();
                os.close();
            }
        }
        /**
         * 收到客户端请求了!
         */
    }
    

    UDP

    image.png
    image.png
    image.png
    image.png

    示例小结

    public class UDPTest {
    
        /**
         * 发生端
         */
        @Test
        public void sender() throws IOException {
            //1创建socket,发送端不需要指定要发生的ip和端口,直接在要发生的包里指定接收的地址端口即可。
            DatagramSocket socket = new DatagramSocket();
            byte[] data = "我是发送端,这是给你的一封信!".getBytes();
            //数据包要发送的地址
            InetAddress address = InetAddress.getByName("127.0.0.1");
            //2创建发送包
            DatagramPacket packet = new DatagramPacket(data, 0, data.length, address, 9999);
            //3发送
            socket.send(packet);
            System.out.println("发送数据成功!");
            //4关闭流
            socket.close();
        }
    
    
        /**
         * 接收端
         */
        @Test
        public void receiver() throws IOException {
            //1创建接收端socket,要指定接收端的端口号,才能接收
            DatagramSocket socket = new DatagramSocket(9999);
            //2创建用于接收数据流的数组容器
            byte[] buffer = new byte[1024];
            //2创建接收包,用于接收数据包
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
            //3发送
            socket.receive(packet);
            //4打印接收到的数据
            System.out.println(new String(packet.getData(),0,packet.getLength()));
            System.out.println("接收数据成功!");
            //5关闭流
            socket.close();
        }
    }
    

    URL

    image.png
    image.png

    示例小结

    public class URLTest {
    
        /**
         * 使用url去下载网络文件
         *
         * @throws IOException
         */
        @Test
        public void urlTest() throws IOException {
            //URL相当于种子
            URL url = new URL("https://pics4.baidu.com/feed/d009b3de9c82d1586f9efd2871ac9ad1bd3e42bf.jpeg?token=dd219671927c0cb92aebbd8808110a70");
            //根据不同的协议强转不同的urlConnection,HttpsURLConnection或者HttpURLConnection
            HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
            InputStream is = urlConnection.getInputStream();
            //写到本地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("pic.jpeg"));
            byte[] buff = new byte[1024];
            int len;
            while ((len = is.read(buff)) != -1) {
                bos.write(buff, 0, len);
            }
            System.out.println("下载成功了!");
            //关闭流
            is.close();
            bos.close();
            urlConnection.disconnect();
        }
    }
    

    参考

    Java入门视频教程

    618-630

  • 相关阅读:
    thinkPHP中怎么访问域名直接跳到后台登录页面
    使用ajax方法实现form表单的提交
    微信小程序根据生日获取年龄
    微信小程序出现 text 设置行高 line-height 无效的问题
    微信小程序中换行,空格(多个空格)写法
    如何用css实现弧度圆角?三角形以及圆形
    微信小程序的bindtap事件
    JS控制只能输入数字并且最多允许小数点两位
    微信小程序如何做金额输入限制
    微信小程序使用函数的三种方法
  • 原文地址:https://www.cnblogs.com/castamere/p/15636341.html
Copyright © 2020-2023  润新知