黑马网络编程学习

目录

网络编程概述

网络通信三要素

三要素概述、要素一:IP地址

IP地址操作类-inetAddress

要素二:端口号

要素三:协议

UDP通信

UDP通信:快速入门

UDP通信:多发多收

UDP通信-广播、组播

TCP通信-快速入门

编写客户端代码

编写服务端代码、原理分析

TCP通信-多发多收消息

​编辑TCP通信-同时接受多个客户端消息

TCP通信-使用线程池优化

TCP通信案例-即时通信

TCP通信案例-模拟BS系统 


网络编程概述

网络通信三要素

三要素概述、要素一:IP地址

IP地址操作类-inetAddress

要素二:端口号

要素三:协议

 

UDP通信

UDP通信:快速入门

 实现UDP一发一收

/**
 * 接受端 服务端
 */
public class ClicentDemo2 {
    public static void main(String[] args) throws IOException {
        //1、创建接收端对象:注册端口(人)
        DatagramSocket socket = new DatagramSocket(8888);

        //2、创建一个数据包接收数据(韭菜盘子)
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        //3、等待接收数据
        socket.receive(packet);
        int len = packet.getLength();

        //4、取出数据
        String s = new String(buffer,0,len);
        System.out.println("收到了:" + s);
        socket.close();
    }
}
/**
 * 发送端  一发一收
 */
public class ClicentDemo1 {
    public static void main(String[] args) throws Exception {

        //1、创建发送端对象 发送端自带默认端口号
        DatagramSocket socket = new DatagramSocket();

        //2、创建数据包对象封装对象(韭菜盘子)
        /*
        * 参数一:封装要发送的数据(韭菜)
        * 参数二:数据大小
        * 参数三:对方ip地址
        * 参数四:服务端端口*/
        byte[] buffer = "我是一颗韭菜".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(),8888);

        //3、发送数据
        socket.send(packet);

        socket.close();
    }
}

UDP通信:多发多收

/**
 * 接受端 服务端 多发多收
 */
public class ClicentDemo2 {
    public static void main(String[] args) throws IOException {
        System.out.println("=====服务端启动====");
        //1、创建接收端对象:注册端口(人)
        DatagramSocket socket = new DatagramSocket(8888);

        //2、创建一个数据包接收数据(韭菜盘子)
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while (true) {
            //3、等待接收数据
            socket.receive(packet);
            int len = packet.getLength();

            //4、取出数据
            String s = new String(buffer,0,len);
            System.out.println("收到了来自:" + packet.getAddress() + ",对方端口是" + packet.getPort() + "的消息:" + s);
        }
    }
}






/**
 * 发送端  多发多收
 */
public class ClicentDemo1 {
    public static void main(String[] args) throws Exception {
        //1、创建发送端对象 发送端自带默认端口号
        DatagramSocket socket = new DatagramSocket();

        //2、创建数据包对象封装对象(韭菜盘子)
        /*
        * 参数一:封装要发送的数据(韭菜)
        * 参数二:数据大小
        * 参数三:对方ip地址
        * 参数四:服务端端口*/
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            byte[] buffer = msg.getBytes();
            if ("exit".equals(msg)){
                System.out.println("离线成功!");
                socket.close();
                break;
            }
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(),8888);

            //3、发送数据
            socket.send(packet);
        }


    }
}

UDP通信-广播、组播

 发送端:

接收端:

TCP通信-快速入门

编写客户端代码

 

 

public class Client {
    public static void main(String[] args) {
        //1、创建Socket通信管道请求有服务器的连接
        //参数一:服务端的IP地址
        //参数二:服务端的端口
        try {
            Socket socket = new Socket("127.0.0.1",7777);

            //2、从socket管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //3.把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            //4.发送消息
            ps.println("我是TCP的客户端,我已经与你对接,并发出邀请。");
            ps.flush();

            //关闭程序
            //socket.close(); 此处可不直接关闭资源,防止传输出错。
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

编写服务端代码、原理分析

/**
 * 目标:开发Socket网络编程入门代码的服务器,实现接受消息
 */
public class Server {
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            //1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //2、必须调用accept方法,等等待接收客户端的Socket连接请求,建立Socket管道
            Socket socket = serverSocket.accept();
            //3、从socket管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //4、把字节输入流包装成缓冲字符输入流进行消息的接受
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //5.按照行读取消息
            String msg;
            if ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:" + msg);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

TCP通信-多发多收消息

发送端/客户端进行部分修改

            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说");
                String msg = sc.nextLine();
                //4.发送消息
                ps.println(msg);
                ps.flush();
            }

接收端进行部分修改

while ((msg = br.readLine()) != null)

TCP通信-同时接受多个客户端消息

/**
 * 目标:开发Socket网络编程入门代码的服务器,实现可以同时接收多个客户端消息
 */
public class Server {
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            //1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //定义一个死循环由主线程负责不断接收客户端的Socket管道连接。
            while (true) {
                //2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取。
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + "上线了!!!");
                //3、开始创建独立线程处理Socket
                new ServerReaderThread(socket).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}


public class ServerReaderThread extends Thread{
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接受
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息。

            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:" + msg);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!");       }

    }
}

TCP通信-使用线程池优化

/**
 * 目标:使用线程池优化,实现通信。
 */
public class Server {
    //使用静态变量记住一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(3,5, 6,TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
    public static void main(String[] args) {

        try {
            System.out.println("===服务端启动成功===");
            //1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //定义一个死循环由主线程负责不断接收客户端的Socket管道连接。
            while (true) {
                //2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取。
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + "上线了!!!");
                Runnable target = new ServerReaderThread(socket);
                pool.execute(target);

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}


public class ServerReaderRunnable implements Runnable{
    private Socket socket;

    public ServerReaderRunnable(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接受
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息。

            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:" + msg);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!");
        }
    }
}

客户端代码无需修改

 

TCP通信案例-即时通信

/**
 * 目标:即时通讯
 * 1、客户端发送消息
 * 1、客户端随时可能需要收到消息
 */
public class Client {
    public static void main(String[] args) {
        //1、创建Socket通信管道请求有服务器的连接
        //参数一:服务端的IP地址
        //参数二:服务端的端口
        try {
            System.out.println("===客户端启动===");
            Socket socket = new Socket("127.0.0.1",7777);

            //创建一个独立的线程专门负责整个客户端的读消息(服务器随时可能发消息过来)
            new ClientReadrThread(socket).start();
            //2、从socket管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //3.把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说");
                String msg = sc.nextLine();
                //4.发送消息
                ps.println(msg);
                ps.flush();
            }
            //关闭程序
            //socket.close(); 此处可不直接关闭资源,防止传输出错。
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

class ClientReadrThread extends Thread{
    private Socket socket;

    public ClientReadrThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接受
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息。

            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println("收到消息" + msg);
            }
        } catch (IOException e) {
            System.out.println("服务端把你踢出去了....");
        }
    }
}




/**
 * 目标:即时通信
 */
public class Server {

    //定义一个静态的List集合存储当前全部在线的socket管道
    public static List<Socket> allOnlineSocket = new ArrayList<>();
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            //1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //定义一个死循环由主线程负责不断接收客户端的Socket管道连接。
            while (true) {
                //2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取。
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + "上线了!!!");
                allOnlineSocket.add(socket);
                //3、开始创建独立线程处理Socket
                new ServerReaderRunnable(socket).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}




public class ServerReaderRunnable extends Thread{
    private Socket socket;

    public ServerReaderRunnable(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接受
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息。

            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:" + msg);
                //把这个消息进行端口转发给全部的客户端Socket管道
                sendMsgToall(msg);
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!");
            Server.allOnlineSocket.remove(socket);
        }
    }

    private void sendMsgToall(String msg) throws IOException {
        for (Socket socket : Server.allOnlineSocket) {
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println(msg);
            ps.flush();
        }
    }
}

TCP通信案例-模拟BS系统 

public class ServerReaderRunnable extends Thread{
    private Socket socket;

    public ServerReaderRunnable(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //浏览器 已经与本线程建立了Socket管道
            //响应消息给浏览器显示
            PrintStream ps = new PrintStream(socket.getOutputStream());
            //必须响应HTTP协议格式数据,否则浏览器不认识消息
            ps.println("HTTP/1.1 200 OK"); //协议类型和版本 响应成功的消息!
            ps.println("Content-Type:text/html;charset=UTF-8");  //响应的数据类型:文本、网页
            ps.println(); //必须发送一个空行

            ps.println("<span style='color:red;font-size:90px'>澳门倒闭人啊!!!</span>");
            ps.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值