java 网络编程笔记

网络编程三要素:

1,协议,计算机在网络中通信需要遵守的规则,常见的协议有:

TCP协议(传输控制协议),面向连接,数据安全,传输速度慢。三次握手。

UDP协议(用户数据报协议),面向无连接,传输数据不安全,数据包可能丢失。传输速度快。

2,IP地址,用来标记网络中的计算机设备

3,端口号,0-65525,用来标记计算器设备中正在运行的程序。


/**
 * InetAddress类
 *
 * public static InetAddress getLocalHost()
 * 获得本机主机的ip对象
 *  public static InetAddress getByName(String host)
 *  通过ip地址字符串或者主机名获得对应的ip地址对象
 *  String getHostName()
 *  获取本机主机名
 *  public String getHostAddress()
 *  获取本机的ip地址
 */
public class Test {
    /**
     * InetAddress类
     *
     * public static InetAddress getLocalHost()
     * 获得本机主机的ip对象
     *  public static InetAddress getByName(String host)
     *  通过ip地址字符串或者主机名获得对应的ip地址对象
     *  String getHostName()
     *  获取本机主机名
     *  public String getHostAddress()
     *  获取本机的ip地址
     */
    public static void main(String[] args) throws UnknownHostException {
        //获得本机主机的ip对象:DESKTOP-CINLR4D/192.168.200.1
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        //通过ip地址字符串或者主机名获得对应的ip地址对象:www.baidu.com/14.215.177.38
        InetAddress byName = InetAddress.getByName("www.baidu.com");
        System.out.println(byName);
        //获取本机主机名DESKTOP-CINLR4D
        String hostName = localHost.getHostName();
        System.out.println(hostName);
        //获取本机的ip地址192.168.200.1
        System.out.println(localHost.getHostAddress());
    }
}
/**
 * java.net.Socket一个该类的对象就表示一个客户端程序
 * Socket(String host,Int port)根据ip和端口号创建客户端Socket对象
 * *注意事项:
 * 只要执行该方法,就会立即连接指定的服务器程序,如果连接不成功,则会报异常。
 * 如果连接成功表示三次握手通过.
 * 常用方法:
 * public OutputStream getOutputStream()
 * 获取字节输出流对象
 * public InputStream getInputStream()
 * 获取字节输入流对象
 * void close()
 * 关闭Socket,会自动关闭相关的流
 */
public class Test {
    /**
     * 客户端
     */
    public static void main(String[] args) throws IOException {
        /**
         * java.net.Socket一个该类的对象就表示一个客户端程序
         * Socket(String host,Int port)根据ip和端口号创建客户端Socket对象
         * *注意事项:
         * 只要执行该方法,就会立即连接指定的服务器程序,如果连接不成功,则会报异常。
         * 如果连接成功表示三次握手通过.
         * 常用方法:
         * public OutputStream getOutputStream()
         * 获取字节输出流对象
         * public InputStream getInputStream()
         * 获取字节输入流对象
         * void close()
         * 关闭Socket,会自动关闭相关的流
         */
        Socket socket = new Socket("127.0.0.1", 8088);
        InputStream inputStream = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("服务器你好".getBytes(StandardCharsets.UTF_8));
        byte[] b = new byte[8192];
        int len;
        while ((len = inputStream.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }

        socket.close();
    }
}
/**
 * java.net.ServerSocket该类的一个对象表示一个服务端
 * ServerSocket(int port)
 * 根据指定端口号开启服务器
 * 常用方法:
 * public Socket accept()
 * 等待客户端连接,并且获得与客户端关联的Socket对象,如果客户端没有连接,
 * 该方法会一直阻塞
 */
public class Test2 {
    /**
     * 服务端
     */
    public static void main(String[] args) throws IOException {
        /**
         * java.net.ServerSocket该类的一个对象表示一个服务端
         * ServerSocket(int port)
         * 根据指定端口号开启服务器
         * 常用方法:
         * public Socket accept()
         * 等待客户端连接,并且获得与客户端关联的Socket对象,如果客户端没有连接,
         * 该方法会一直阻塞
         */
        ServerSocket serverSocket = new ServerSocket(8088);

        while (true){
            System.out.println("等待客户端连接。。。");
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            OutputStream outputStream = accept.getOutputStream();
            byte[] b = new byte[8192];
            int len;
            while ((len = inputStream.read(b))!=-1){
                System.out.println("服务器接受到了客户端请求"+new String(b,0,len));
                outputStream.write(b,0,len);
            }

        }
    }
}

通过上面方法会发现一个问题,就是客户端给服务端写数据,客户端读取到-1后并不会把-1给服务端,所以服务端一直在等待-1,然后客户端也在等待服务端的-1,然后超时就会报异常。

解决办法,每次向对方写完数据,都要调用一下shutdownOutput方法,告诉对方传输数据结束了。如下:

public class Test {
    /**
     * 客户端
     */
    public static void main(String[] args) throws IOException {
        /**
         * java.net.Socket一个该类的对象就表示一个客户端程序
         * Socket(String host,Int port)根据ip和端口号创建客户端Socket对象
         * *注意事项:
         * 只要执行该方法,就会立即连接指定的服务器程序,如果连接不成功,则会报异常。
         * 如果连接成功表示三次握手通过.
         * 常用方法:
         * public OutputStream getOutputStream()
         * 获取字节输出流对象
         * public InputStream getInputStream()
         * 获取字节输入流对象
         * void close()
         * 关闭Socket,会自动关闭相关的流
         */
        Socket socket = new Socket("127.0.0.1", 8088);
        InputStream inputStream = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("服务器你好".getBytes(StandardCharsets.UTF_8));
        //每次向对方写完数据都,都要调用一下shutdownOutput方法,告诉对方传输数据结束了
        socket.shutdownOutput();

        byte[] b = new byte[8192];
        int len;
        while ((len = inputStream.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }

        socket.close();
    }
}
public class Test2 {
    /**
     * 服务端
     */
    public static void main(String[] args) throws IOException {
        /**
         * java.net.ServerSocket该类的一个对象表示一个服务端
         * ServerSocket(int port)
         * 根据指定端口号开启服务器
         * 常用方法:
         * public Socket accept()
         * 等待客户端连接,并且获得与客户端关联的Socket对象,如果客户端没有连接,
         * 该方法会一直阻塞
         */
        ServerSocket serverSocket = new ServerSocket(8088);

        while (true){
            System.out.println("等待客户端连接。。。");
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            OutputStream outputStream = accept.getOutputStream();
            byte[] b = new byte[8192];
            int len;
            while ((len = inputStream.read(b))!=-1){
                System.out.println("服务器接受到了客户端请求"+new String(b,0,len));
                outputStream.write(b,0,len);
            }
            //每次向对方写完数据都,都要调用一下shutdownOutput方法,告诉对方传输数据结束了
            accept.shutdownOutput();
        }
    }
}

服务端多线程

public class Test2 {
    /**
     * 服务端
     */
    public static void main(String[] args) throws IOException {
        /**
         * java.net.ServerSocket该类的一个对象表示一个服务端
         * ServerSocket(int port)
         * 根据指定端口号开启服务器
         * 常用方法:
         * public Socket accept()
         * 等待客户端连接,并且获得与客户端关联的Socket对象,如果客户端没有连接,
         * 该方法会一直阻塞
         */
        ServerSocket serverSocket = new ServerSocket(8088);

        while (true){
            System.out.println("等待客户端连接。。。");
            Socket accept = serverSocket.accept();
            //多线程
            new Thread(()->{
                try {
                    InputStream inputStream = accept.getInputStream();
                    OutputStream outputStream = accept.getOutputStream();
                    byte[] b = new byte[8192];
                    int len;
                    while ((len = inputStream.read(b))!=-1){
                        System.out.println("服务器接受到了客户端请求"+new String(b,0,len));
                        outputStream.write(b,0,len);
                    }
                    //每次向对方写完数据都,都要调用一下shutdownOutput方法,告诉对方传输数据结束了
                    accept.shutdownOutput();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

模拟web服务器

public class Test {
    /**
     * 模拟B/S服务器
     */
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            //字符缓冲流特有方法,读取一行
            String s = bufferedReader.readLine();
            System.out.println(s);//GET /index.html HTTP/1.1
            String[] s1 = s.split(" ");
            String filePath = s1[1].substring(1);
            System.out.println(filePath);
            //然后通过文件名读
            FileInputStream fileInputStream = new FileInputStream("网络编程\\"+filePath);

            OutputStream outputStream = socket.getOutputStream();
            byte[] b = new byte[8192];
            int len;
            /**
             * 写入响应头文件
             */
            outputStream.write("HTTP/1.1 200 ok\r\n".getBytes());
            outputStream.write("Content-Type: text/html;charset=utf-8\r\n".getBytes());
            outputStream.write("\r\n".getBytes());
            while ((len = fileInputStream.read(b)) != -1){
                System.out.println(new String(b,0,len));
                outputStream.write(b,0,len);
            }
            socket.shutdownOutput();
        }
        //byte[] b = new byte[8192];
        //int len = inputStream.read(b);

        //打印浏览器的请求信息,发现目前只有第一行有用,
        // 所以我们InputStream字节流转成字符流
        //System.out.println(new String(b,0,len));
            /**
             * GET /index.html HTTP/1.1
             * Host: 127.0.0.1:8888
             * Connection: keep-alive
             * sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
             * sec-ch-ua-mobile: ?0
             * sec-ch-ua-platform: "Windows"
             * Upgrade-Insecure-Requests: 1
             * User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
             * Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,
             * */


        //serverSocket.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值