网络编程

第九章——网络编程

1、网络编程概述

计算机网络:
是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。极域
网络编程:
就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

2、网络模型

image-20241019141003861

3、网络通信三要素

1、IP地址:InetAddress
网络中设备的标识,不易记忆,可用主机名
2、端口号
用于标识进程的逻辑地址,不同进程的标识
3、传输协议
通讯的规则
常见协议:TCP,UDP

4、协议UDP和TCP

UDP
将数据源和目的封装成数据包中,不需要建立连接;每个数据报包的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快
TCP
建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低

    
/*
    1:建立客户端的Socket服务,并明确要连接的服务器。
    2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
    3:通过Socket对象的方法,可以获取这两个流
    4:通过流的对象可以对数据进行传输
    5:如果传输数据完毕,关闭资源

 */
public class ClientDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立客户端的Socket服务,并明确要连接的服务器。
        //Socket(String host, int port)
        //创建流套接字并将其连接到指定主机上的指定端口号。
        Socket socket = new Socket("192.168.22.15", 12345);
        Scanner sc = new Scanner(System.in);

        // 3:通过Socket对象的方法,可以获取这两个流
        //获取通道中的输出流,将数据发送给服务端
        OutputStream outputStream = socket.getOutputStream();
        //获取通道中的输入流
        InputStream inputStream = socket.getInputStream();

        while (true){
            System.out.print("请输入要发送的内容:");
            String info = sc.nextLine();
            if("886".equals(info)){
                break;
            }

            // 4:通过流的对象可以对数据进行传输
            outputStream.write(info.getBytes());
            outputStream.flush(); // 来自于通道中的类


            byte[] bytes = new byte[1024];
            int length = inputStream.read(bytes);
            String s = new String(bytes, 0, length);
            System.out.println(s);
        }


        // 5:如果传输数据完毕,关闭资源
//        outputStream.close();
        socket.close();

    }
}    
============================================================ /*
    1:建立服务器端的socket服务,需要一个端口
    2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
    3:通过客户端的获取流对象的方法,读取数据或者写入数据
    4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

 */
public class ServerDemo1 {
    public static void main(String[] args){
        try {
            // 1:建立服务器端的socket服务,需要一个端口
            //ServerSocket(int port)
            //创建绑定到指定端口的服务器套接字。
            ServerSocket ss = new ServerSocket(12345);

            // 2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
            Socket socket = ss.accept();

            while (true){
                InetAddress inetAddress = socket.getInetAddress();
                String hostName = inetAddress.getHostName();

                // 3:通过客户端的获取流对象的方法,读取数据或者写入数据
                // 获取通道中的输入流
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1024];
                int length = inputStream.read(bytes);
                String s = new String(bytes, 0, length);
                System.out.println(hostName+": "+s);

                // 获取通道中的输出流
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("服务器已接收!".getBytes());
                outputStream.flush();
            }
        }catch (Exception e){
            System.out.println("用户已退出。。。");
        }


    }
}   
============================================================ /*
    1:建立客户端的Socket服务,并明确要连接的服务器。
    2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
    3:通过Socket对象的方法,可以获取这两个流
    4:通过流的对象可以对数据进行传输
    5:如果传输数据完毕,关闭资源

 */
public class ClientDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立客户端的Socket服务,并明确要连接的服务器。
        //Socket(String host, int port)
        //创建流套接字并将其连接到指定主机上的指定端口号。
        Socket socket = new Socket("192.168.22.15", 12345);
        Scanner sc = new Scanner(System.in);

        // 3:通过Socket对象的方法,可以获取这两个流
        //获取通道中的输出流,将数据发送给服务端
        OutputStream outputStream = socket.getOutputStream();
        //获取通道中的输入流
        InputStream inputStream = socket.getInputStream();

        while (true){
            System.out.print("请输入要发送的内容:");
            String info = sc.nextLine();
            if("886".equals(info)){
                break;
            }

            // 4:通过流的对象可以对数据进行传输
            outputStream.write(info.getBytes());
            outputStream.flush(); // 来自于通道中的类


            byte[] bytes = new byte[1024];
            int length = inputStream.read(bytes);
            String s = new String(bytes, 0, length);
            System.out.println(s);
        }


        // 5:如果传输数据完毕,关闭资源
//        outputStream.close();
        socket.close();

    }
}   

============================================================
    
/*
    1:建立服务器端的socket服务,需要一个端口
    2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
    3:通过客户端的获取流对象的方法,读取数据或者写入数据
    4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

 */
public class ServerDemo1 {
    public static void main(String[] args)  throws Exception{
        // 1:建立服务器端的socket服务,需要一个端口
        //ServerSocket(int port)
        //创建绑定到指定端口的服务器套接字。
        ServerSocket ss = new ServerSocket(12345);
        System.out.println("=============== 欢迎进入32期聊天室 ===================");

        while (true){
            // 2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
            Socket socket = ss.accept();

            new TCPThread(socket).start();
        }
    }
}

class TCPThread extends Thread{

    Socket socket;

    public TCPThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InetAddress inetAddress = socket.getInetAddress();
        String hostName = inetAddress.getHostName();
        System.out.println("用户:"+hostName+" 已上线! ");
        try {
            while (true) {
                // 3:通过客户端的获取流对象的方法,读取数据或者写入数据
                // 获取通道中的输入流
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1024];
                int length = inputStream.read(bytes);
                String s = new String(bytes, 0, length);
                String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                System.out.println(time);
                System.out.println(hostName + ": " + s);
                System.out.println();

                // 获取通道中的输出流
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("服务器已接收!".getBytes());
                outputStream.flush();
            }
        }catch (Exception e){
            System.out.println("-----------------------");
            System.out.println(hostName+" 用户已下线....");
            System.out.println("-----------------------");
        }
    }
}
============================================================
/*
    1:建立客户端的Socket服务,并明确要连接的服务器。
    2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
    3:通过Socket对象的方法,可以获取这两个流
    4:通过流的对象可以对数据进行传输
    5:如果传输数据完毕,关闭资源

 */
public class ClientDemo1 {
    public static void main(String[] args) throws Exception {
        // 1:建立客户端的Socket服务,并明确要连接的服务器。
        //Socket(String host, int port)
        //创建流套接字并将其连接到指定主机上的指定端口号。
        Socket socket = new Socket("192.168.22.15", 12345);
        Scanner sc = new Scanner(System.in);



        // 3:通过Socket对象的方法,可以获取这两个流
        //获取通道中的输出流,将数据发送给服务端
        OutputStream outputStream = socket.getOutputStream();
        //获取通道中的输入流
        InputStream inputStream = socket.getInputStream();

        // E:\\李刚的对象.jpg
        BufferedInputStream bis = null;
        while (true){
            try {
                System.out.print("请输入要上传文件的路径:");
                String address = sc.nextLine();
                bis = new BufferedInputStream(new FileInputStream(address));
                break;
            }catch (Exception e){
                System.out.println("路径不存在!重新输入!");
            }
        }
        if(bis!=null){
            byte[] bytes = new byte[2048];
            int length = 0;
            while ((length = bis.read(bytes))!=-1){
                // 4:通过流的对象可以对数据进行传输
                outputStream.write(bytes,0, length);
                outputStream.flush(); // 来自于通道中的类
            }
        }

        //关闭输出流,通知服务端读取结束
        socket.shutdownOutput();

        // 接收服务端的反馈
        byte[] bytes = new byte[1024];
        int length = inputStream.read(bytes);
        String s = new String(bytes, 0, length);
        System.out.println(s);


        // 5:如果传输数据完毕,关闭资源
//        outputStream.close();
        socket.close();

    }
}
============================================================

/*
    1:建立服务器端的socket服务,需要一个端口
    2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
    3:通过客户端的获取流对象的方法,读取数据或者写入数据
    4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

 */
public class ServerDemo1 {
    public static void main(String[] args)  throws Exception{
        // 1:建立服务器端的socket服务,需要一个端口
        //ServerSocket(int port)
        //创建绑定到指定端口的服务器套接字。
        ServerSocket ss = new ServerSocket(12345);

        while (true){
            // 2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
            Socket socket = ss.accept();

            new TCPThread(socket).start();
        }
    }
}

class TCPThread extends Thread{

    Socket socket;

    public TCPThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InetAddress inetAddress = socket.getInetAddress();
        String hostName = inetAddress.getHostName();
        System.out.println("用户:"+hostName+" 已上线! ");

        try {
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\target\\" + hostName + "-" + System.currentTimeMillis() + ".jpg"));
            while (true) {
                // 3:通过客户端的获取流对象的方法,读取数据或者写入数据
                // 获取通道中的输入流
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[2048];
                int length = 0;
                while ((length = inputStream.read(bytes))!=-1){
                    // 4:通过流的对象可以对数据进行传输
                    bos.write(bytes,0, length);
                    bos.flush(); // 来自于通道中的类
                }

                // 获取通道中的输出流
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write("图片已上传!!".getBytes());
                outputStream.flush();
            }
        }catch (Exception e){
            System.out.println("-----------------------");
            System.out.println(hostName+" 用户已下线....");
            System.out.println("-----------------------");
        }
    }
}
============================================================
/*
    1:建立udp的socket服务.
    2:通过receive方法接收数据
    3:将收到的数据存储到数据包对象中
    4:通过数据包对象的功能来完成对接收到数据进行解析.
    5:可以对资源进行关闭

 */
public class ReceiveDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立udp的socket服务
        DatagramSocket socket = new DatagramSocket(10086);

        // 2:通过receive方法接收数据
        //public synchronized void receive(DatagramPacket p)
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
        socket.receive(packet);

        //4:通过数据包对象的功能来完成对接收到数据进行解析.
        byte[] data = packet.getData();
        int length = packet.getLength();
        String info = new String(data, 0, length);
        System.out.println("发送段发来一条消息:"+info);


        // 5:可以对资源进行关闭
        socket.close();

    }
}
============================================================

/*
    1:建立udp的socket服务
    2:将要发送的数据封装成数据包
    3:通过udp的socket服务,将数据包发送出
    4:关闭资源

 */
public class SendDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立udp的socket服务
        // DatagramSocket
        //DatagramSocket()
        //构造数据报套接字并将其绑定到本地主机上的任何可用端口。
        DatagramSocket socket = new DatagramSocket();

        // 2:将要发送的数据封装成数据包 DatagramPacket
        //DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
        byte[] bytes = "李刚来了...".getBytes();
        int length = bytes.length;
        InetAddress address = InetAddress.getByName("192.168.22.15");
        DatagramPacket packet = new DatagramPacket(bytes, length, address, 10086);


        // 3:通过udp的socket服务,将数据包发送出
        //public void send(DatagramPacket p)
        socket.send(packet);

        // 4:关闭资源
        socket.close();

    }
}
============================================================
/*
    1:建立udp的socket服务.
    2:通过receive方法接收数据
    3:将收到的数据存储到数据包对象中
    4:通过数据包对象的功能来完成对接收到数据进行解析.
    5:可以对资源进行关闭

 */
public class ReceiveDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立udp的socket服务
        DatagramSocket socket = new DatagramSocket(10086);
        System.out.println("=================== 欢迎来到32期大群聊 =======================");

        while (true){
            // 2:通过receive方法接收数据
            //public synchronized void receive(DatagramPacket p)
            byte[] bytes = new byte[1024];
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
            socket.receive(packet);

            //4:通过数据包对象的功能来完成对接收到数据进行解析.
            byte[] data = packet.getData();
            int length = packet.getLength();
            String info = new String(data, 0, length);

            InetAddress address = packet.getAddress();
            String hostName = address.getHostName();
            BufferedWriter bw = new BufferedWriter(new FileWriter("java/src/com/shujia/day19/recode/" + hostName + ".txt",true));

            if("886".equals(info)){
                System.out.println("----------- 提示线 -------------");
                System.out.println(hostName+" 用户已离开群聊.....");
                System.out.println("----------- 提示线 -------------");
//                break;
            }else {
                String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                System.out.println(time);
                System.out.println(hostName+ ":"+info);
                bw.write(time);
                bw.newLine();
                bw.write(info);
                bw.newLine();
                bw.flush();

                System.out.println();
            }
        }


        // 5:可以对资源进行关闭
//        socket.close();

    }
}
============================================================
/*
    1:建立udp的socket服务
    2:将要发送的数据封装成数据包
    3:通过udp的socket服务,将数据包发送出
    4:关闭资源

 */
public class SendDemo1 {
    public static void main(String[] args) throws Exception{
        // 1:建立udp的socket服务
        // DatagramSocket
        //DatagramSocket()
        //构造数据报套接字并将其绑定到本地主机上的任何可用端口。
        DatagramSocket socket = new DatagramSocket();
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);

        while (true){
            System.out.print("请输入要发送的内容:");
            String info = sc.nextLine();


            // 2:将要发送的数据封装成数据包 DatagramPacket
            //DatagramPacket(byte[] buf, int length, InetAddress address, int port)
            //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
            byte[] bytes = info.getBytes();
            int length = bytes.length;
            InetAddress address = InetAddress.getByName("192.168.22.15");
            DatagramPacket packet = new DatagramPacket(bytes, length, address, 10086);

            // 3:通过udp的socket服务,将数据包发送出
            //public void send(DatagramPacket p)
            socket.send(packet);

            if("886".equals(info)){
                break;
            }
        }

        // 4:关闭资源
        socket.close();

    }
}


posted @ 2024-10-19 16:43  snzjz  阅读(17)  评论(0)    收藏  举报