java socket网络编程增强

网络基础知识

  • 端口号1024以下的尽量不要使用(大多已被互联网厂商使用)
  • 资源定位:
    URL(Uniform Resource Locator) 统一资源定位器,他是一种具体的URI
    URI(Uniform Resource Identifier) 统一资源标识符,用来唯一的标识一个资源

InetAddress类和InetSocketAddress类

/**
 * InetAddress类的使用
 * 没有封装端口
 * @author L J
 */
public class InetDemo {
    public static void main(String[] args) throws UnknownHostException {
        //通过getLocalHost()方法创建InetAddress对象
        InetAddress addr = InetAddress.getLocalHost();
        System.out.println(addr.getHostAddress()); //本机IPv4地址:10.56.0.107
        System.out.println(addr.getHostName());    //输出本机计算机名

        //根据域名得到InetAddress对象
        addr = InetAddress.getByName("www.baidu.com");
        System.out.println(addr.getHostAddress()); //返回百度服务器的IP地址:180.97.33.107
        System.out.println(addr.getHostName());    //www.baidu.com

        //根据IP地址得到InetAddress对象
        addr = InetAddress.getByName("180.97.33.107");
        System.out.println(addr.getHostAddress()); //返回百度服务器的IP地址:180.97.33.107
        System.out.println(addr.getHostName());    //180.97.33.107
    }
}
/**
 * InetSocketAddress类的使用
 * 在InetAddress的基础上+端口
 * @author L J
 */
public class InetDemo2 {
    public static void main(String[] args) {
        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
        System.out.println(address.getHostName());  //127.0.0.1
        System.out.println(address.getPort());      //9999
        InetAddress addr = address.getAddress();
        System.out.println(addr.getHostAddress());  //127.0.0.1
        System.out.println(addr.getHostName());     //127.0.0.1
    }
}

URL

组成:协议+资源所在的主机域名+端口号+资源文件

public class URLDemo {
    public static void main(String[] args) throws MalformedURLException {
        //绝对路径构建
        URL url = new URL("http://www.baidu.com:80/index.html#a?username = root");
        System.out.println("协议:" + url.getProtocol()); //http
        System.out.println("域名:" + url.getHost());     //www.baidu.com
        System.out.println("端口:" + url.getPort());      //80
        System.out.println("资源:" + url.getFile());     //   /index.html
        System.out.println("相对路径:" + url.getPath());  //   /index.html
        System.out.println("锚点:" + url.getRef());       //a?username = root
        //getQuery方法,如果存在锚点,返回null;不存在就返回参数
        System.out.println("参数:" + url.getQuery());    //null,如果去掉#a,返回username = root

        //相对路径构建
        url = new URL("http://www.baidu.com:80/a/");
        url = new URL(url, "b");
        System.out.println(url.toString()); //  http://www.baidu.com:80/a/b
    }
}
/**
 * 获取资源
 * 爬虫第一步
 * @author L J
 */
public class URLDemo2 {
    public static void main(String[] args) throws IOException {
        URL url = new URL("http://www.baidu.com");

        /*获取资源网络流
        InputStream is = url.openStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while(-1 != (len = is.read(buf))) {
            System.out.println(new String(buf, 0 ,len));
        }
        is.close();
        */

        BufferedReader br = 
            new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:/DB/baidu.html"), "UTF-8"));
        String msg = null;
        while((msg = br.readLine()) != null) {
            bw.append(msg);
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}

聊天室+私聊

发送数据线程:

/**
 * 发送数据线程
 * @author L J
 */
public class Send implements Runnable{
    private BufferedReader console; //控制台输入流
    private DataOutputStream dos;   //输出流
    private boolean isRunning = true; //线程是否存活
    private String name;  //昵称

    public Send() {
        console = new BufferedReader(new InputStreamReader(System.in));
    }

    public Send(Socket client, String name) {
        this();
        try {
            dos = new DataOutputStream(client.getOutputStream());
            this.name = name;
            send(this.name);
        } catch (IOException e) {
            isRunning = false;
            //关闭输出流和控制台输入流
            CloseUtil.close(dos, console);
        }
    }

    //从控制台读取数据
    private String getMsgFromConsole() {
        try {
            return console.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    //发送数据
    public void send(String msg) {
        try {
            if(msg != null && !msg.equals("")) {
                dos.writeUTF(msg);
                dos.flush();
            }
        } catch (IOException e) {
            isRunning = false;
            //关闭输出流和控制台输入流
            CloseUtil.close(dos, console);
        }
    }

    /**
     * 1、从控制台读取数据
     * 2、发送数据
     */
    @Override
    public void run() {
        while(isRunning) {
            send(getMsgFromConsole());
        }
    }
}

接收数据线程:

/**
 * 接收数据线程
 * @author L J
 */
public class Receive implements Runnable{
    private DataInputStream dis; //输入流
    private boolean isRunning = true; //线程是否存活

    public Receive() {
    }

    public Receive(Socket client) {
        try {
            dis = new DataInputStream(client.getInputStream());
        } catch (IOException e) {
            isRunning = false;
            CloseUtil.close(dis);
        }
    }

    /**
     * 接收数据
     * @return 接收到的数据
     */
    public String receive() {
        String msg = "";
        try {
            msg = dis.readUTF();
        } catch (IOException e) {
            isRunning = false;
            CloseUtil.close(dis);
        }
        return msg;
    }

    @Override
    public void run() {
        while(isRunning) {
            System.out.println(receive());
        }
    }
}

关闭流工具:

/**
 * 关闭流工具类
 * @author L J
 */
public class CloseUtil {
    //关闭流
    public static void close(Closeable ... io) {
        for(Closeable temp : io) {
            if(temp != null) {
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

客户端:

/**
 * 聊天客户端
 * 1、写出数据:输出流
 * 2、读取数据:输入流
 * 
 * 输入与输出在同一个线程内,应该独立处理
 * 
 * @author L J
 */
public class ChatClient {
    public static void main(String[] args) throws IOException, IOException {
        Socket client = new Socket("localhost", 9999);
        System.out.println("请输入昵称:");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String name = br.readLine();

        if(name.equals("")) {
            return;
        }

        //发送数据,一条独立的路径
        new Thread(new Send(client, name)).start();

        //接收数据,一条独立的路径
        new Thread(new Receive(client)).start();
    }
}

服务器端:

/**
 * 聊天服务器
 * 
 * @author L J
 */
public class ChatServer {
    //管理道路
    private List<MyChannel> all = new ArrayList<MyChannel>();

    public static void main(String[] args) throws IOException {
        new ChatServer().start();
    }

    public void start() throws IOException {
        ServerSocket server = new ServerSocket(9999);
        while(true) {
            Socket client = server.accept();
            MyChannel channel = new MyChannel(client);
            all.add(channel); //统一管理所有的道路
            new Thread(channel).start();  //一条道路
        }
    }

    /**
     * 一个客户端一条道路
     * @author L J
     */
    private class MyChannel implements Runnable {
        // 输入流
        private DataInputStream dis;
        // 输出流
        private DataOutputStream dos;
        //昵称
        private String name;
        // 线程是否存活
        private boolean isRunning = true;

        // 一个客户端一条道路
        public MyChannel(Socket client) {
            try {
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
                this.name = dis.readUTF();
                this.send("欢迎进入聊天室!");
                sendToOthers(this.name + "加入了聊天室!", true);
            } catch (IOException e) {
                isRunning = false;
                CloseUtil.close(dos, dis);
            }
        }

        /**
         * 接收数据
         * @return 接收到的数据
         */
        public String receive() {
            String msg = "";
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                isRunning = false;
                CloseUtil.close(dis);
                all.remove(this); //将出错的道路移除
            }
            return msg;
        }

        /**
         * 发送数据
         * 
         * @param msg
         */
        public void send(String msg) {
            if (msg == null && msg.equals("")) {
                return;
            }
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                isRunning = false;
                // 关闭输入输出流
                CloseUtil.close(dos);
                all.remove(this); //将出错的道路移除
            }
        }

        /**
         * 发送数据给其他客户端
         */
        private void sendToOthers(String msg, boolean sys) {
            //是否为私聊
            if(msg.startsWith("@") && msg.indexOf(":") > -1) {//私聊
                //获取昵称
                String name = msg.substring(1, msg.indexOf(":"));
                String content = msg.substring(msg.indexOf(":") + 1);
                for(MyChannel theOne : all) {
                    if(theOne.name.equals(name)) {
                        theOne.send(this.name + ":" + content);
                    }
                }
            }else{//群聊
                //遍历容器
                for(MyChannel other : all) {
                    //不发送给自己
                    if(other == this) {
                        continue;
                    }else{
                        if(sys) {//系统信息
                            other.send("系统信息:" + msg);
                        }else{
                            //发送给其它客户端
                            other.send(this.name + ":" + msg);
                        }
                    }
                }
            }
        }

        /**
         * 接收数据,并发送给其他客户端
         */
        @Override
        public void run() {
            while(isRunning) {
                sendToOthers(receive(), false);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值