• java回顾之Socket网络编程


    java回顾之Socket网络编程

    一、软件结构

    C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件

    特点:

      优点:
        对网络要求不是很高
      缺点:
        开发维护周期长
        占用空间

    B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等

     特点 

      优点:
        开发维护周期短
        不占用空间
      缺点:
        对网络网速要求高

    二、网络编程三要素

    ip地址:

        ip地址是计算机的唯一标识。互联网上面的每个设备都有唯一的ip地址

        查ip的命令:ipconfig

      ip的分类

      IPV4:有4个255的段落,192.168.31.56。IPV4已经被全世界的设备用光了

      IPV6: ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 ,号称能给世界的每一粒沙子分配一个不重复的IP

    端口号:

      端口号是软件的唯一标识。每个软件都有一个唯一的端口号,范围是0~65535,其中0~1023是留给系统使用的要 避开。

    协议:  

      协议是传输数据的方式

      TCP:面向连接,安全,效率低

      三次握手

      UDP:面向无连接,不安全,效率高,对数据包有大小限制不能超过64K

    三、InetAddress类

    InetAddress类成员方法
      * static InetAddress getLocalHost()
    获得本地主机IP地址对象
      * static InetAddress getByName(String host)
    根据IP地址字符串或主机名获得对应的IP地址对象

      * String getHostName() 获得主机名
      * String getHostAddress() 获得IP地址字符串

    四、TCP通信程序

    代码演示:

        客户端发送数据

    public class Demo客户端 {
        public static void main(String[] args) throws IOException {
    
            //创建套接字对象
            //客户端要指定给谁发送数据
            //第一个参数是对方的ip  第二个参数是对方的端口
            Socket s = new Socket("192.168.31.87",8888);
    
            //Socket里面包含输出流和输入流,我们网络编程需要获取底层流完成数据发送
    
            //获取输出流
            OutputStream os = s.getOutputStream();
            //键盘输入内容发送
            Scanner sc = new Scanner(System.in);
            String str = sc.nextLine();
            //输出(把字符串转成字节数组)
            os.write(str.getBytes());
    
    
            //关闭资源
            s.close();
        }
    }
    

        服务端接收数据

    public class Demo服务器端 {
        public static void main(String[] args) throws IOException {
            //创建服务器对象
            //参数代表的是自己的端口
            ServerSocket ss = new ServerSocket(8888);
    
            //接受客户单的连接
            //阻塞(如果连接不到客户端就会一直等待)
            Socket s = ss.accept();
    
            //获取输入流
            InputStream is = s.getInputStream();
    
            //接受数据
            byte[] arr = new byte[1024];
            //默认发送的时候就只发了一句话,不需要使用循环读取
            int len = is.read(arr);
    
            //打印
            System.out.println("客户端对我说:" + new String(arr,0,len));
    
            //关闭资源
            s.close();
            //ss.close();服务器打开之后一般不会关闭
        }
    }
    

     4.3、TCP模拟聊天

            客户端代码
       public class Demo客户端 {
        public static void main(String[] args) throws IOException {
    
            //创建套接字对象
            //客户端要指定给谁发送数据
            //第一个参数是对方的ip  第二个参数是对方的端口
            Socket s = new Socket("192.168.31.87",9999);
    
            //Socket里面包含输出流和输入流,我们网络编程需要获取底层流完成数据发送
    
            while(true) {
                //获取输出流
                OutputStream os = s.getOutputStream();
                //键盘输入内容发送
                Scanner sc = new Scanner(System.in);
                String str = sc.nextLine();
                //输出(把字符串转成字节数组)
                os.write(str.getBytes());
    
    
                //接受数据
                //获取输入流
                InputStream is = s.getInputStream();
                byte[] arr = new byte[1024];
                //读取内容
                int len = is.read(arr);
                //打印
                System.out.println("服务器对我说: " + new String(arr, 0, len));
    
            }
    
            //关闭资源
            //s.close();
        }
    }
    

      

     服务端代码:

    public class Demo服务器端 {
        public static void main(String[] args) throws IOException {
            //创建服务器对象
            //参数代表的是自己的端口
            ServerSocket ss = new ServerSocket(9999);
    
            //接受客户单的连接
            Socket s = ss.accept(); //阻塞(如果连接不到客户端就会一直等待)
    
            while(true) {
    
                //获取输入流
                InputStream is = s.getInputStream();
                //接受数据
                byte[] arr = new byte[1024];
                //默认发送的时候就只发了一句话,不需要使用循环读取
                int len = is.read(arr);
                //打印
                System.out.println("客户端对我说:" + new String(arr, 0, len));
    
    
                //发送数据
                //获取输出流
                OutputStream os = s.getOutputStream();
                //发送固定语句
                os.write("滚".getBytes());
    
            }
    
            //关闭资源
            //s.close();
            //ss.close();服务器打开之后一般不会关闭
    
        }
    }
    

      

    4.4、文件上传案例

    客户端发送文件
    public class Demo文件上传的客户端 {
        public static void main(String[] args) throws IOException {
    
            //创建对象
            //Socket s = new Socket("127.0.0.1",5678);
            //Socket s = new Socket("localhost",5678);
            Socket s = new Socket("192.168.31.87",5678);
    
            //创建输入流
            FileInputStream fis = new FileInputStream("C:\资料\小资料\微信图片_20190108110420.jpg");
            //获取输出流
            OutputStream os = s.getOutputStream();
    
            //每次读取一个字节发送给服务器
            int i;
            while((i = fis.read()) != -1){
                //输出
                os.write(i);
            }
    
            //关闭资源
            fis.close();
            s.close();
        }
    }
    
    
        服务器接收文件
    public class Demo文件上传的服务器端 {
        public static void main(String[] args) throws IOException {
    
            //创建对象
            ServerSocket ss = new ServerSocket(5678);
            //获取客户端连接
            Socket s = ss.accept();
    
            //获取输入流
            InputStream is = s.getInputStream();
            //创建输出流
            FileOutputStream fos = new FileOutputStream("day18\上传图片.jpg");
    
            //每次读取一个字节输出一个字节
            int i;
            while ((i=is.read()) != -1){
                fos.write(i);
            }
    
            //关流
            fos.close();
            s.close();
        }
    }
    

     有个循环发送的问题。 

    解决办法:

      

    • 客户端停止发送数据之后,需要通知服务器:

          s.shutdownOutput();

    4.6、模拟B/S服务器

    B/S模式是web的内容,以下是服务器需要给浏览器发送的响应信息,在正式传输数据前,要先写这个。
    - 
    
    ```
    发送图片:
    	"HTTP/1.1 200 OK
    Content-Type:image/jpeg
    
    "
    发送文字时:
    	"HTTP/1.1 200 OK
    Content-Type:text/html;charset=UTF-8
    
    "
    ```
    
    - 服务器端
    public class Demo服务器 {
    
        public static void main(String[] args) {
            try {
                //创建服务器对象
                ServerSocket ss = new ServerSocket(7890);
    
                while (true) {
                    //接受浏览器的请求
                    Socket s = ss.accept();
                    //获取输入流
                    InputStream is = s.getInputStream();
    
                    //调用读取一行字符串的方法
                    //readLine()
                    BufferedReader br = new BufferedReader(new InputStreamReader(is));
                    String str = br.readLine();
                    //从浏览器发过来的数据
                    //System.out.println(str);   //  GET /1.jpg HTTP/1.1
    
                    //1.截取用户要访问的资源名称
                    String[] arr = str.split(" ");
                    String name = arr[1];  //    /1.jpg
    
                    //2.查找文件是否存在
                    File f = new File("day18/发车" + name);  //路径: day18/发车/4.jpg
    
                    //3.获取输出流
                    BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
    
                    if (f.exists()) {
                        //4.创建输入流
                        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(f));
    
                        //要访问的资源存在
                        //如果存在把图片发送给浏览器
                        os.write("HTTP/1.1 200 OK
    Content-Type:image/jpeg
    
    ".getBytes());
                        //发送数据
                        int i;
                        while ((i = fis.read()) != -1) {
                            os.write(i);
                        }
    
                        //关流
                        fis.close();
    
                    } else {
                        //要访问的资源不存在
                        //如果不存在给浏览器"你要访问的资源被外星人劫持了404~"
                        os.write("HTTP/1.1 200 OK
    Content-Type:text/html;charset=UTF-8
    
    ".getBytes());
                        os.write("你要访问的资源被外星人劫持了404~".getBytes());
    
                    }
                    //关流
                    os.close();
    
                    //关闭
                    s.close();
    
                }
    
            }catch (Exception e){
                //如果你想看报错信息
                //e.printStackTrace();
            }
    
        }
    }
    
    - 上面的代码是单线程代码,当多个浏览器都访问同一个服务器时。服务器需要一个一个处理。
    - 接下来我们写一个多线程代码。为每一次访问都开启一个线程
    
    public class Demo服务器多线程 {
        public static void main(String[] args) throws Exception{
    
                //创建服务器对象
                ServerSocket ss = new ServerSocket(7890);
                //可以接受多个浏览器的访问
                while(true){
                    //接受浏览器的请求
                    Socket s = ss.accept();
                    //每次接收到浏览器请求就开启新线程
                    //使用Lambda表达式开启多线程(Runnable是一个函数式接口)
                    Thread t = new Thread(()->{
    
                        try {
                            //获取输入流
                            InputStream is = s.getInputStream();
    
                            //调用读取一行字符串的方法
                            //readLine()
                            BufferedReader br = new BufferedReader(new InputStreamReader(is));
                            String str = br.readLine();
                            //从浏览器发过来的数据
                            //System.out.println(str);   //  GET /1.jpg HTTP/1.1
    
                            //1.截取用户要访问的资源名称
                            String[] arr = str.split(" ");
                            String name = arr[1];  //    /1.jpg
    
                            //2.查找文件是否存在
                            File f = new File("day18/发车" + name);  //路径: day18/发车/4.jpg
    
                            //假设每次执行都需要3秒钟,这样为了看到多线程的效果
                            Thread.sleep(3000);
    
                            //3.获取输出流
                            BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
    
                            if (f.exists()) {
                                //4.创建输入流
                                BufferedInputStream fis = new BufferedInputStream(new FileInputStream(f));
    
                                //要访问的资源存在
                                //如果存在把图片发送给浏览器
                                os.write("HTTP/1.1 200 OK
    Content-Type:image/jpeg
    
    ".getBytes());
                                //发送数据
                                int i;
                                while ((i = fis.read()) != -1) {
                                    os.write(i);
                                }
    
                                //关流
                                fis.close();
    
                            } else {
                                //要访问的资源不存在
                                //如果不存在给浏览器"你要访问的资源被外星人劫持了404~"
                                os.write("HTTP/1.1 200 OK
    Content-Type:text/html;charset=UTF-8
    
    ".getBytes());
                                os.write("你要访问的资源被外星人劫持了404~".getBytes());
    
    
                            }
                            //关流
                            os.close();
    
                            //关闭
                            s.close();
                        }catch (Exception e){
                            //异常处理
                        }
                    });
                    t.start();
                }
        }
    
  • 相关阅读:
    iis aspx常见错误 没有对“C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files”的写访问权限。
    Windows 下 Apache HTTP Server 安装、配置以及与 Tomcat 的整合(附图)
    Xstudio+Bugzilla
    测试管理工具列表大全
    bitmap详细介绍
    Android学习绘制图形
    PorterDuff.Mode
    盒模型及文本溢出
    css属性继承
    CSS层叠样式
  • 原文地址:https://www.cnblogs.com/gushiye/p/13894210.html
Copyright © 2020-2023  润新知