Java 【网络编程】学习笔记

网络编程

IP

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * InetAddress: 多个静态方法
 * 1.getLocalHost:本机
 * 2.getByName:根据域名DNS || IP地址 ———>IP
 *
 * 两个成员方法:
 * 1.getHostAddress:返回地址
 * 2.getHostName:返回计算机名
 */
public class IPTest {
    public static void main(String[] args) throws UnknownHostException {
        //使用getLocalHost方法创建InetAddress对象  本机
        InetAddress address = InetAddress.getLocalHost();
        System.out.println(address.getHostAddress());
        System.out.println(address.getHostName());
        //根据域名得到InetAddress对象
        address = InetAddress.getByName("www.163.com");
        System.out.println(address.getHostAddress());
        System.out.println(address.getHostName());
        //根据IP得到InetAddress对象
        address = InetAddress.getByName("121.22.230.62");
        System.out.println(address.getHostAddress());
        System.out.println(address.getHostName());//输出的IP不是域名,如果这个IP地址不存在或DNS服务器不允许进行IP地址和域名的映射,getHostName方法就直接返回这个IP地址
    }
}

端口

  1. 查看所有端口: netstat-ano•

  2. 查看指定端口: netstat-aon|findstr"808"

  3. 查看指定进程: tasklist|findstr"808"

  4. 查看具体程序:使用任务管理器查看 PID

import java.net.InetSocketAddress;

/**
 * 端口:
 * 1.区分软件
 * 2. 2个字节 0-65535 UDP TCP
 * 3.同一个协议端口不能冲突
 * 4.定义端口越大越好
 * InetSocketAddress
 * 1.构造器
 * new InetSocketAddress(地址|域名,8080);
 * 2.方法
 * getAddress()
 * getPort()
 * getHostName()
 */
public class PortTest {
    public static void main(String[] args) {
        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
        InetSocketAddress socketAddress1 = new InetSocketAddress("localhost",9000);
        System.out.println(socketAddress.getHostName());
        System.out.println(socketAddress1.getAddress());
        System.out.println(socketAddress1.getPort());
    }
}

URL

import java.net.MalformedURLException;
import java.net.URL;

/**
 * 统一资源定位器 互联网三大基石之一(HTML http),区分资源
 * 1.协议
 * 2.域名或计算机名
 * 3.端口 :默认80
 * 4.请求资源
 * http:||www.baidu.com:80|index.html?uname=shsxt&age=18#a
 */
public class URLTest {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://www.csdn.net");
        //获取四个值
        System.out.println("协议"+url.getProtocol());
        System.out.println("域名|IP"+url.getHost());
        System.out.println("请求资源"+url.getFile());
        System.out.println("请求资源"+url.getPath());
        System.out.println("端口"+url.getPort());
        //参数
        System.out.println("参数"+url.getQuery());
        //锚点
        System.out.println("锚点"+url.getRef());
    }
}

爬虫原理

import java.io.*;
import java.net.URL;

/**
 * 网络爬虫的原理
 */
public class SpiderTest01 {
    public static void main(String[] args) throws IOException {
        //获取URL
        URL url = new URL("https://www.csdn.net/");
        //下载资源
        InputStream inputStream = url.openStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        String msg =null;
        while (null!=(msg = bufferedReader.readLine())){
            System.out.println(msg);
        }
        bufferedReader.close();
    }
}


/**
 * 网络爬虫的原理+模拟浏览器
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class SpiderTest02 {
    public static void main(String[] args) throws IOException {
        //获取URL
        URL url = new URL("https://www.csdn.net/");
        //下载资源
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("......");
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        String msg =null;
        while (null!=(msg = bufferedReader.readLine())){
            System.out.println(msg);
        }
        bufferedReader.close();
    }
}

UDP网络编程

基本步骤

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;

/**
 * 基本流程:
 * 发送端
 * 1.使用DatagramSocket创建发送端  (指定端口)
 * 2.准备数据 一定转成字节数组
 * 3.封装成DatagramPacket 包裹 需要指定目的地
 * 4.发送包裹 send(DatagramPacket p)
 * 5.释放资源
 */
public class UDPClient {
    public static void main(String[] args) throws Exception{
        System.out.println("发送方启动中......");
        DatagramSocket client = new DatagramSocket(8888);
        String data = "上海尚学堂";
        byte[] datas = data.getBytes();
        DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",9999));
        client.send(packet);
        client.close();
    }
}

/**
 * 基本流程:
 * 接收端
 * 1.使用DatagramSocket创建接收端  (指定端口)
 * 2.准备容器 封装成DatagramPacket 包裹
 * 3.阻塞式接受包裹 recieve(DatagramPacket p)
 * 4.分析数据
 *  byte[] getData()
 *  getLength()
 */
public class UDPServer {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方启动中......");
        DatagramSocket server = new DatagramSocket(6666);
        byte[] container = new byte[1024*60];
        DatagramPacket packet = new DatagramPacket(container,0,container.length);
        server.receive(packet);
        byte[] datas = packet.getData();
        int len = packet.getLength();
        System.out.println(new String(datas,0,len));

    }
}

上传文件

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
 * 基本流程:
 * 发送端
 * 1.使用DatagramSocket创建发送端  (指定端口)
 * 2.准备数据 一定转成字节数组
 * 3.封装成DatagramPacket 包裹 需要指定目的地
 * 4.发送包裹 send(DatagramPacket p)
 * 5.释放资源
 */
public class UDPTypeClient {
    public static void main(String[] args) throws Exception{
        System.out.println("发送方启动中......");
        DatagramSocket client = new DatagramSocket(8888);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
        dos.writeUTF("编码辛酸泪");
        dos.writeInt(18);
        dos.writeBoolean(false);
        dos.writeChar('a');
        dos.flush();
        byte[] datas = baos.toByteArray();
        DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
        client.send(packet);
        client.close();
    }
}


import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * 基本流程:
 * 接收端
 * 1.使用DatagramSocket创建接收端  (指定端口)
 * 2.准备容器 封装成DatagramPacket 包裹
 * 3.阻塞式接受包裹 recieve(DatagramPacket p)
 * 4.分析数据  将字节数组还原为对应的类型
 *  byte[] getData()
 *  getLength()
 */
public class UDPTypeServer {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方启动中......");
        DatagramSocket server = new DatagramSocket(6666);
        byte[] container = new byte[1024*60];
        DatagramPacket packet = new DatagramPacket(container,0,container.length);
        server.receive(packet);
        byte[] datas = packet.getData();
        int len = packet.getLength();
        DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
        //顺序与写出一致
        String msg = dataInputStream.readUTF();
        int age = dataInputStream.readInt();
        boolean flag = dataInputStream.readBoolean();
        char ch = dataInputStream.readChar();
        System.out.println(msg+"-->"+flag);
        server.close();

    }
}

案例:在线咨询

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
 * 发送端 :使用面向对象封装
 */
public class TalkSend implements Runnable{
    private DatagramSocket client;
    private BufferedReader reader;
    private String toIp;
    private int toPort;
    public TalkSend(int port,String toIp,int toPort)  {
        this.toIp = toIp;
        this.toPort = toPort;
        try {
            client = new DatagramSocket(port);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        while(true){
            String data = null;
            try {
             data = reader.readLine();
            byte []datas = data.getBytes();
            DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
            client.send(packet);
            if (data.equals("bye")){
                break;
            }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        client.close();
    }
}


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.regex.Pattern;

/**
 * 接收端:使用面向对象封装
 */
public class TalkRecieve implements Runnable{
    private DatagramSocket server;
    private String from;
    public TalkRecieve(int port,String from){
        this.from = from;
        try {
            server = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        while (true) {
            byte[] container = new byte[1024 * 60];
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            try {
                server.receive(packet);
                byte[] datas = packet.getData();
                int len = packet.getLength();
                String data = new String(datas, 0, len);
                System.out.println(from+":"+data);
                if (data.equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}


/**
 * 加入多线程,实现双向交流 模拟在线咨询
 */
public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(7777,"localhost",9999)).start();//发送

        new Thread(new TalkRecieve(8888,"老师")).start();
    }
}

/**
 * 加入多线程,实现双向交流 模拟在线咨询
 */
public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkRecieve(9999,"学生")).start();//接收

        new Thread(new TalkSend(5555,"localhost",8888)).start();
    }
}

TCP网络编程

基本步骤

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 熟悉流程
 * 创建服务器
 * 1.指定端口 使用ServerSocket 创建服务器
 * 2.阻塞式等待连接 accept
 * 3.操作:输入输出流操作
 * 4.释放资源
 */
public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("-----创建服务器-----");
        //1.指定端口 使用ServerSocket 创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        Socket client = server.accept();
        System.out.println("一个客户端建立了连接");
        //3.操作:输入输出流操作
        DataInputStream dis = new DataInputStream(client.getInputStream());
        String data = dis.readUTF();
        System.out.println(data);
        //4.释放资源
        dis.close();
        client.close();
        server.close();
    }
}

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 熟悉流程
 * 创建客户端
 * 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
 * 2.操作: 输入输出流操作
 * 3.释放资源
 */
public class Client {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        //1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.操作: 输入输出流操作
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        String data = "hello";
        dos.writeUTF(data);
        dos.flush();
        //3.释放资源
        dos.close();
        client.close();
    }
}

单向登录

/**
 * 模拟登录 单向
 * 创建客户端
 * 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
 * 2.操作: 输入输出流操作
 * 3.释放资源
 */
public class LoginClient {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名");
        String uname = console.readLine();
        System.out.println("请输入密码");
        String upwd = console.readLine();
        //1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.操作: 输入输出流操作
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());

        dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
        dos.flush();
        //3.释放资源
        dos.close();
        client.close();
    }
}


import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 模拟登录 单向
 * 创建服务器
 * 1.指定端口 使用ServerSocket 创建服务器
 * 2.阻塞式等待连接 accept
 * 3.操作:输入输出流操作
 * 4.释放资源
 */
public class LoginServer {
    public static void main(String[] args) throws IOException {
        System.out.println("-----创建服务器-----");
        //1.指定端口 使用ServerSocket 创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        Socket client = server.accept();
        System.out.println("一个客户端建立了连接");
        //3.操作:输入输出流操作
        DataInputStream dis = new DataInputStream(client.getInputStream());
        String datas= dis.readUTF();
        //分析
        String []datasArray = datas.split("&");
        for (String info:datasArray){
            String[] userinfo = info.split("=");
            System.out.println(userinfo[0]+"-->"+userinfo[1]);
            if (userinfo[0].equals("uname")){
                System.out.println("你的用户名为:"+userinfo[1]);
            }else if (userinfo[0].equals("upwd")){
                System.out.println("你的密码为:"+userinfo[1]);
            }
        }
        //4.释放资源
        dis.close();
        client.close();

    }
}

双向登录

import java.io.*;
import java.net.Socket;
/**
 * 模拟登录 双向
 * 创建客户端
 * 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
 * 2.操作: 输入输出流操作
 * 3.释放资源
 */
public class LoginTwoWayClient {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名");
        String uname = console.readLine();
        System.out.println("请输入密码");
        String upwd = console.readLine();
        //1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.操作: 输入输出流操作
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
        dos.flush();

        DataInputStream dis = new DataInputStream(client.getInputStream());
        String result= dis.readUTF();

        System.out.println(result);
        //3.释放资源
        dos.close();
        client.close();
    }
}


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 模拟登录 双向
 * 创建服务器
 * 1.指定端口 使用ServerSocket 创建服务器
 * 2.阻塞式等待连接 accept
 * 3.操作:输入输出流操作
 * 4.释放资源
 */
public class LoginTwoWayServer {
    public static void main(String[] args) throws IOException {
        System.out.println("-----创建服务器-----");
        //1.指定端口 使用ServerSocket 创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        Socket client = server.accept();
        System.out.println("一个客户端建立了连接");
        //3.操作:输入输出流操作
        DataInputStream dis = new DataInputStream(client.getInputStream());
        String datas= dis.readUTF();
        String uname = "";
        String upwd ="";
        //分析
        String []datasArray = datas.split("&");
        for (String info:datasArray){
            String[] userinfo = info.split("=");
            System.out.println(userinfo[0]+"-->"+userinfo[1]);
            //分析
            if (userinfo[0].equals("uname")){
                System.out.println("你的用户名为:"+userinfo[1]);
                uname = userinfo[1];
            }else if (userinfo[0].equals("upwd")){
                System.out.println("你的密码为:"+userinfo[1]);
                upwd = userinfo[1];
            }
        }
        //输出
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());

        if (uname.equals("lwz") && upwd.equals("123456")){
                dos.writeUTF("登录成功,欢迎回来");
        }else{
                dos.writeUTF("用户名或密码错误");
        }
        dos.flush();
        //4.释放资源
        dis.close();
        client.close();

    }
}

文件上传

import java.io.*;
import java.net.Socket;

/**
 * 上传文件
 * 创建客户端
 * 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
 * 2.操作: 输入输出流操作
 * 3.释放资源
 */
public class FileClient {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        //1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.操作: 输入输出流操作  拷贝上传
        InputStream is = new BufferedInputStream(new FileInputStream("E:\\Download\\ThreadStudy\\lantian.jpg"));
        OutputStream os = new BufferedOutputStream(client.getOutputStream());
        byte []flush = new byte[1024];
        int len = -1;
        while ((len=is.read(flush))!=-1){
            os.write(flush,0,len);
        }
        os.flush();
        os.close();
        is.close();
        //3.释放资源
        client.close();
    }
}


/**
 * 存储文件
 * 创建服务器
 * 1.指定端口 使用ServerSocket 创建服务器
 * 2.阻塞式等待连接 accept
 * 3.操作:输入输出流操作
 * 4.释放资源
 */
public class FileServer {
    public static void main(String[] args) throws IOException {
        System.out.println("-----创建服务器-----");
        //1.指定端口 使用ServerSocket 创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        Socket client = server.accept();
        System.out.println("一个客户端建立了连接");
        //3.操作:输入输出流操作
        InputStream is = new BufferedInputStream(client.getInputStream());
        OutputStream os = new BufferedOutputStream(new FileOutputStream("src/tcp.png"));
        byte []flush = new byte[1024];
        int len = -1;
        while ((len=is.read(flush))!=-1){
            os.write(flush,0,len);
        }
        os.flush();
        os.close();
        is.close();
        //4.释放资源

        client.close();
        server.close();
    }
}

多用户登录

import java.io.*;
import java.net.Socket;

public class LoginMultiClient {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        Socket client = new Socket("localhost",8888);
        new Send(client).send();
        new Recieve(client).recieve();
        client.close();

    }
    static class Send{
        private Socket client;
        private BufferedReader br;
        private DataOutputStream dos;
        private String msg;
        public Send(Socket client){
            try {
                this.client = client;
                br = new BufferedReader(new InputStreamReader(System.in));
                this.msg = init();
                dos = new DataOutputStream(client.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private String init(){
            try {
                System.out.println("请输入用户名");
                String uname = br.readLine();
                System.out.println("请输入密码");
                String upwd = br.readLine();
                return "uname=" + uname + "&pwd=" + upwd;
            }catch (IOException e){
                e.printStackTrace();
            }
            return "";
        }
        public void send(){
            try {
                dos.writeUTF(this.msg);
                dos.flush();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    static class Recieve{
        private Socket client;
        private DataInputStream dis;
        public Recieve(Socket client){
            this.client = client;
            try {
                dis = new DataInputStream(client.getInputStream());
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        public void recieve(){
            String response;
            try {
                response = dis.readUTF();
                System.out.println(response);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class LoginMultiServer{
    public static void main(String[] args) throws IOException {
        System.out.println("-----server-----");
        ServerSocket server = new ServerSocket(8888);
        boolean isRuning  = true;
        while (isRuning){
            Socket socket = server.accept();
            System.out.println("一个客户端建立了连接");
            new Thread(new Channel(socket)).start();
        }
        server.close();

    }
    static class Channel implements Runnable{
        private Socket socket;
        private DataInputStream dis;
        private DataOutputStream dos;

        public Channel(Socket client){
            this.socket = client;
            try {
                dis = new DataInputStream(socket.getInputStream());
                dos = new DataOutputStream(socket.getOutputStream());
            }catch (IOException e){
                e.printStackTrace();
                release();
            }
        }
        public String recieve(){
            String datas = "";
            try {
                datas = dis.readUTF();
            }catch (IOException e){
                e.printStackTrace();
            }
            return datas;
        }
        public void send(String msg){
            try {
                dos.writeUTF(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void release(){
            if (null!=dos){
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null!=dis){
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null!=dos){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void run() {
            String datas = recieve();
            String []dataArray = datas.split("&");
            String uname = null;
            String upwd = null;
            for (String info:dataArray) {
                String[] userinfo = info.split("=");
                if ("uname".equals(userinfo[0])) {
                    uname = userinfo[1];
                    System.out.println("用户名:" + uname);
                } else if ("pwd".equals(userinfo[0])) {
                    upwd = userinfo[1];
                    System.out.println("密码:" + upwd);
                }
            }
            if (uname.equals("zs")&& upwd.equals("123")){
                send("登录成功,欢迎回来");
            }else {
                send("用户名或密码错误");
            }
            release();
        }
    }

}

手写聊天室

基础简易版

import java.io.*;
import java.net.Socket;

/**
 * 在线聊天室: 客户端
 * 目标: 实现一个客户可以正常收发多条消息
 */
public class TMultiClient {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        //1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.客户端发送消息
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        DataInputStream dis = new DataInputStream(client.getInputStream());
        boolean isRunning = true;
        while (isRunning) {
            String msg = console.readLine();
            dos.writeUTF(msg);
            dos.flush();
            //3.获取消息
            msg = dis.readUTF();
            System.out.println(msg);
        }
        //4.释放资源
        dos.close();
        dis.close();
        client.close();

    }
}


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 在线聊天室 :服务端
 * 目标:实现一个客户可以正常收发多条信息
 * 问题:其他客户必须等待之前的客户退出,才能继续 排队
 * 问题:
 * 1.代码不好维护
 * 2.哭护短读写没有分开 必须先写后读
 */
public class TMultiChat {
    public static void main(String[] args) throws IOException {
        System.out.println("-----创建服务器-----");
        //1.指定端口 使用ServerSocket 创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        while (true) {
            Socket client = server.accept();
            System.out.println("一个客户端建立了连接");
            //3.接收消息
            new Thread(()->{
                DataInputStream dis =null;
                DataOutputStream dos= null;
                try {
                    dis = new DataInputStream(client.getInputStream());
                    dos = new DataOutputStream(client.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                boolean isRunning = true;
                while (isRunning) {
                    String msg = null;
                    try {
                        msg = dis.readUTF();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    //4.返回消息
                    try {
                        dos.writeUTF(msg);
                        dos.flush();
                    } catch (IOException e) {
                        //e.printStackTrace();
                        isRunning = false;//停止线程
                    }
                    //释放资源
                }
                try {
                    if (null==dos){
                        dos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (null==dis){
                        dis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (null==client){
                        client.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

        }


    }
}

最终版

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.Channel;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 在线聊天室 :服务器
 * 目标:私聊
 */
public class Chat {
    private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<Channel>();
    public static void main(String[] args) throws IOException {
        System.out.println("-----Server-----");
        //1.指定端口 使用ServerSocket创建服务器
        ServerSocket server = new ServerSocket(8888);
        //2.阻塞式等待连接 accept
        while (true) {
            Socket client = server.accept();
            System.out.println("一个客户端进行了连接");
            Channel c = new Channel(client);
            all.add(c);  //管理所有的成员
            new Thread(c).start();
        }
    }

    //一个客户代表一个Channel
    static class Channel implements Runnable {
        private DataInputStream dis;
        private DataOutputStream dos;
        private Socket client;
        private boolean isRunning;
        private String name;

        public Channel(Socket client) {
            this.client = client;
            try {
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
                isRunning = true;
                //获取名称
                this.name= recieve();
                //欢迎你的到来
                this.send("欢迎你的到来");
                sendOthers(this.name+"来到了太理1号楼308宿舍聊天室",true);
            } catch (IOException e) {
                System.out.println("-----1-----");
                release();
            }
        }

        //接收消息
        private String recieve() {
            String msg = "";
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                System.out.println("-----2-----");
                release();
            }
            return msg;
        }

        //发送消息
        private void send(String msg) {
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                System.out.println("-----3-----");
                release();
            }
        }

        /**
         * 群聊:获取自己的消息 发给其他人
         * 私聊:约定数据格式
         */
        private void sendOthers(String msg,boolean isSys) {
            boolean isPrivate = msg.startsWith("@");
            if (isPrivate) { //私聊
                int idx = msg.indexOf(":");
                //获取目标和数据
                String targetName = msg.substring(1, idx);
                msg = msg.substring(idx+1);
                for (Channel other : all) {
                    if (other.name.equals(targetName)) { //目标
                        other.send(this.name + "悄悄地对您说:" + msg);
                        break;
                    }
                }
            } else {
                for (Channel other : all) {
                    if (other == this) { //自己
                        continue;
                    }
                    if (!isSys) {
                        other.send(this.name + "对所有人说:" + msg);//群聊消息
                    } else {
                        other.send(msg); //系统消息
                    }
                }
            }
        }

        //释放资源
        private void release() {
            this.isRunning = false;
            SxtUtils.close(dis,dos,client);
            //退出
            all.remove(this);
            sendOthers(this.name + "离开大家庭...", true);
        }

        @Override
        public void run() {
            while (isRunning) {
                String msg = recieve();
                if (!msg.equals("")) {
                    //send (msg)
                    sendOthers(msg, false);
                }
            }
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 在线聊天室 :客户端
 * 目标 :私聊
 */
public class Client {
    public static void main(String[] args) throws IOException {
        System.out.println("-----Client-----");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名:");
        String name = br.readLine();
        //1.建立连接:使用Socket创建客户端+服务的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.客户端发送消息
        new Thread(new Send(client,name)).start();
        new Thread(new Recieve(client)).start();


    }
}


import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 使用多线程封装:接收端
 * 1.接收消息
 * 2.释放资源
 * 3.重写run
 */
public class Recieve implements Runnable{
    private DataInputStream dis;
    private Socket client;
    private boolean isRunning;
    public Recieve(Socket client){
        this.client = client;
        this.isRunning = true;
        try {
            dis = new DataInputStream(client.getInputStream());
        }catch (IOException e){
            System.out.println("=====2=====");
            release();
        }
    }
    //接受消息
    private String recieve(){
        String msg  =  "";
        try {
            msg = dis.readUTF();
        }catch (IOException e){
            System.out.println("=====4=====");
            release();
        }
        return msg;
    }

    @Override
    public void run() {
        while (isRunning){
            String msg = recieve();
            if (!msg.equals("")){
                System.out.println(msg);
            }
        }
    }
    //释放资源
    private void release(){
        this.isRunning = false;
        SxtUtils.close(dis,client);
    }
}


import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 使用多线程封装:发送端
 * 1.发送消息
 * 2.从控制台获取消息
 * 3.释放资源
 * 4.重写run
 *
 */
public class Send implements Runnable{
    private BufferedReader console;
    private DataOutputStream dos;
    private Socket client;
    private boolean  isRunning;
    private String name;
    public Send(Socket client,String name){
        this.client = client;
        console = new BufferedReader(new InputStreamReader(System.in));
        this.isRunning = true;
        this.name = name;
        try {
            dos = new DataOutputStream(client.getOutputStream());
            //发送名称
            send(name);
        }catch (IOException e){
            System.out.println("===1===");
            this.release();
        }
    }

    @Override
    public void run() {
        while (isRunning){
            String msg = getStrFromConsole();
            if (!msg.equals("")){
                send(msg);
            }
        }
    }
    //发送消息
    private void send(String msg){
        try {
            dos.writeUTF(msg);
            dos.flush();
        }catch (IOException e){
            System.out.println(e);
            System.out.println("===3===");
            release();
        }
    }
    /**
     * 从控制台获取消息
     */
    private String getStrFromConsole(){
        try {
            return console.readLine();
        }catch (IOException e){
            e.printStackTrace();
        }
        return "";
    }
    //释放资源
    private void release(){
        this.isRunning = false;
        SxtUtils.close(dos,client);
    }
}


import java.io.Closeable;

/**
 * 工具类
 */
public class SxtUtils {
    /**
     * 释放资源
     */
    public static void close(Closeable... targets) {
        for (Closeable target:targets){
            try {
                if(null!=target){
                    target.close();
                }
            }catch (Exception e){

            }
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嗨!很高兴回答你关于Java并发编程的问题。请问你想知道什么方面的内容呢?我可以分享一些学习笔记和建议给你。 1. 并发编程基础:了解并发编程的基本概念,如线程、进程、锁、同步等。学习Java中的并发编程模型以及相关的API,如Thread、Runnable、Lock、Condition等。 2. 线程安全性:学习如何保证多线程环境下的数据安全性,了解共享资源的问题以及如何使用同步机制来防止数据竞争和并发问题。 3. 线程间的通信:掌握线程间的通信方式,如使用wait/notify机制、Lock/Condition等来实现线程的协调与通信。 4. 并发容器:学习并发容器的使用,如ConcurrentHashMap、ConcurrentLinkedQueue等。了解它们的实现原理以及在多线程环境下的性能特点。 5. 并发工具类:熟悉Java提供的并发工具类,如CountDownLatch、CyclicBarrier、Semaphore等,它们可以帮助你更方便地实现线程间的协作。 6. 并发编程模式:学习一些常见的并发编程模式,如生产者-消费者模式、读者-写者模式、线程池模式等。了解这些模式的应用场景和实现方式。 7. 性能优化与调试:学习如何分析和调试多线程程序的性能问题,了解一些性能优化的技巧和工具,如使用线程池、减少锁竞争、避免死锁等。 这些只是一些基本的学习笔记和建议,Java并发编程是一个庞大而复杂的领域,需要不断的实践和深入学习才能掌握。希望对你有所帮助!如果你有更具体的问题,欢迎继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值