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);
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章