随笔 -- IO -- Socket/ServerSocket -- Echo(BIO)实例

随笔 -- IO -- Socket/ServerSocket -- 系统概述

Java中提供的专门的网络开发程序包------java.net

Java的网络编程提供的两种通信协议:TCP和UDP

    19.1 IP与InetAddress

      19.1.1 IP地址简介

      19.1.2 InetAddress

        InetAddress类主要表示IP地址,这个类有两个子类:Inet4Address、Inet6Address。

        InetAddress类的常用方法:

        ⊙ public static InetAddress getByName(String host)throws UnknownHostException :通过主机名称得到InetAddress对象

        ⊙ public static InetAddress getLocalHost() throws UnknownHostException : 通过本机得到InetAddress对象

        ⊙ public String getHostName() : 得到IP地址

        ⊙ public boolean isReachable(int timeout)throws IOException : 判断地址是否可以到达,同时指定超时时间。

package java_.net_.demo.java_15_5;

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

public class InetAddressMain {

    public static void main(String[] args) throws Exception {

        InetAddress locAdd = null;
        InetAddress remAdd = null;
        locAdd = InetAddress.getLocalHost();
        remAdd = InetAddress.getByName("www.baidu.com");
        System.out.println("本机名称 :" + locAdd.getHostName());
        System.out.println("本机IP地址 :" + locAdd.getHostAddress());
        System.out.println("百度IP地址 :" + remAdd);
        System.out.println("本机是否可达 :" + locAdd.isReachable(5000));
        System.out.println("百度是否可达 :" + remAdd.isReachable(5000));
    }
}

    19.2 URL与URLConnection

      19.2.1 URL

        URL统一资源定位符,可以直接使用此类找到互联网上的资源(如一个简单的网页)。

        URL类的常用方法:

        ⊙ public URL(String spec) throws MalformedURLException : 根据指定的地址实例化URL对象。

        ⊙ public URL(String protocal,String host,int port,String file) throws MalformedURLException : 实例化URL对象,并指定协议、主机、端口名称、资源文件。

        ⊙ public URLConnection openConnection() throws IOException : 取得一个URLConnection对象。

        ⊙ public final InputStream openStream() throws IOException : 取得输入流。

package java_.net_.demo.java_15_5.URL_;

import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;

public class URLMain {

    public static void main(String[] args) throws Exception{
        
        URL url = new URL("http","www.mldnjava.cn",80,"/curriculum.htm");
        InputStream input = url.openStream();
        Scanner sc = new Scanner(input);
        sc.useDelimiter("\n");
        while(sc.hasNext()){
            System.out.println(sc.next());
        }
    }
}

      19.2.2 URLConnection

        URLConnection是封装访问远程网络资源一般方法的类,通过它可以建立与远程服务器的连接,检查远程资源的一些属性。

        此类的常用方法:

        ⊙ public int getContentLength() : 取得内容的长度。

        ⊙ public String getContentType() : 取得内容的类型。

        ⊙ public InputStream getInputStream() throws IOException : 取得连接的输入流。

        URLConnection对象可以通过URL实例的openConnection()方法取得。

package java_.net_.demo.java_15_5.URLConnection;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;

public class URLConnectionMain {

    public static void main(String[] args) throws Exception{
        
        URL url = new URL("http://www.mldnjava.cn");
        URLConnection urlCon = url.openConnection();
        System.out.println("内容大小 :" + urlCon.getContentLength());
        System.out.println("内容类型 :" + urlCon.getContentType());
        InputStream input = urlCon.getInputStream();
        Scanner sc = new Scanner(input);
        sc.useDelimiter("\n");
        while (sc.hasNext()) {
            System.out.println(sc.next());
        }
    }
}

    19.3 URLEncoder 与 URLDecoder

      在Java中如果要完成编码和解码操作就必须使用URLEncoder 和 URLDecoder两个类。

      URLEncoder 可以为传递的内容进行编码;URLDecoder可以为传递的内容进行解码。

      URLEncoder类常用的方法:

      ⊙ public static Spring encode(String s,String enc) throws UnsupportedEncodingException : 使用指定的编码机制将字符串转换为application/x-www-form-urlencoded格式。

      URLDecoder类的常用方法:

      ⊙ public static Spring decode(String s,String enc) throws UnsupportedEncodingException : 使用指定的编码机制对application/x-www-form-urlencoded字符串解码。

package java_.net_.demo.java_15_5.URLEncoder;

import java.net.URLDecoder;
import java.net.URLEncoder;

public class URLEncoderMain {

    public static void main(String[] args) throws Exception{
        
        String keyWord = "lime甲骨文";
        String encod = URLEncoder.encode(keyWord, "UTF-8");
        System.out.println("编码之后的内容 : " + encod);
        String decod = URLDecoder.decode(encod, "UTF-8");
        System.out.println("解码之后的内容 : " + decod);
    }
}

    19.4 TCP程序设计

      在Java中使用Socket(即套接字)完成TCP程序的开发,使用此类可以方便地简历可靠的、双向的、持续的、点对点的通信连接。

      在Socket的程序开发中,服务器端使用ServerSocket等待客户端连接,对于Java的网络程序来讲,每一个客户端都使用Socket对象表示。

      19.4.1 ServerSocket 类与 Socket 类

        ServerSocket主要用在服务器端程序的开发上,用于接收客户端的连接请求。

        ServerSocket类的常用方法:

        ⊙ public ServerSocket(int port)throws IOException : 创建ServerSocket实例,并指定监听端口。

        ⊙ public Socket accept() throws IOException : 等待客户端连接,此方法连接之前一直阻塞。

        ⊙ public InetAddress getInetAddress() : 返回服务器的IP地址。

        ⊙ public boolean isClosed() : 返回ServerSocket的关闭状态。

        ⊙ public void close() throws IOException : 关闭ServerSocket。

        在服务器端每次运行时都要使用accept()方法等待客户端连接,此方法执行之后服务器端将进入阻塞状态,知道客户端连接之后程序可以向下继续执行。此方法返回值类型是Socket,每一个Socket都表示一个客户端对象。

        Socket类的常用方法:

        ⊙ public Socket(String host,int port) throws UnknownHostException,IOException  : 构造Socket对象,同时指定要连接服务器的主机名称及连接端口。

        ⊙ public InputStream getInputStream() throws IOException : 返回此套接字的输入流。

        ⊙ public OutputStream getOutputStream() throws IOException : 返回此套接字的输入流。

        ⊙ public void close() throws IOException : 关闭此Socket。

        ⊙ public boolean isClosed() : 判断此套接字是否被关闭。

        在客户端,程序可以通过Socket类的getInputStream()方法取得服务器的输入信息,在服务器端可以通过getOutputStream()方法取得客户端的输出信息。

      19.4.2 第一个TCP程序

        Class : ServerSocketMain

package java_.net_.demo.java_15_5.serverSocket;

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

public class ServerSocketMain {

    public static void main(String[] args) throws Exception{
        
        ServerSocket server = new ServerSocket(8888);
        Socket client = null;
        PrintStream out = null;
        int count = 1;
        while(true){
            System.out.println("等待第 " + count + " 个客户端接入");
            client = server.accept();
            System.out.println("第 " + count + " 个客户端已接入");
            count++;
            String resp = "Now is : " + new Date();
            out = new PrintStream(client.getOutputStream());
            out.println(resp);
        }
    }
}

        Class : SocketMain

package java_.net_.demo.java_15_5.socket;

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

public class SocketMain {

    public static void main(String[] args) throws Exception{
        Socket client = new Socket("localhost",8888);
        BufferedReader buf = null;
        buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
        String str = buf.readLine();
        System.out.println("服务器端输出内容 :" + str);
        client.close();
        buf.close();
    }
}

      19.4.3 案例:Echo程序(BIO)

        Echo程序是一个网络编程通信交互的一个经典案例,称为回应程序,即客户端输入那些内容,服务器端会在这些内容前加上“ECHO:”并将信息发回客户端。

        本程序中将通过循环的方式使用accept(),这样,每一个客户端执行完毕后,服务器端都可以重新等待用户连接。

          Class : EchoServer

package limeNet.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {

    public static void main(String[] args) throws Exception {
        ServerSocket server = null;
        Socket client = null;
        PrintStream out = null;
        BufferedReader buf = null;
        server = new ServerSocket(8888);
        boolean f = true;
        while(f){
            System.out.println("服务器运行,等待客户端连接。");
            client = server.accept();
            buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
            out = new PrintStream(client.getOutputStream());
            boolean flag = true;
            while(flag){
                String str = buf.readLine();
                if(null == str || "".equals(str)){
                    flag = false;
                }else{
                    if("bye".equals(str)){
                        flag = false;
                    }else{
                        out.print("ECHO : " + str);
                    }
                }
            }
            out.close();
            buf.close();
            client.close();
        }
        server.close();
    }
}

          Class : EchoClient

package limeNet.client;

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

public class EchoClient {

    public static void main(String[] args) throws Exception, Exception {
        Socket client = null;
        client = new Socket("localhost",8888);
        BufferedReader input = null;
        PrintStream out = null;
        BufferedReader buf = null;
        input = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintStream(client.getOutputStream());
        buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
        boolean flag = true;
        while(flag){
            System.out.print("输入信息:");
            String str = input.readLine();
            out.print(str);
            if("bye".equals(str)){
                flag = false;
            }else{
                String echo = buf.readLine();
                System.out.println(echo);
            }
        }
        client.close();
        buf.close();
    }
}

      19.4.4 在服务器上应用多线程

        对于服务器端来说,如果要加入多线程机制,则应该在每个用户连接之后启动一个新的线程。

        Class : EchoThread

package limeNet.thread.server;

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

public class EchoThread implements Runnable {

    private Socket accept;

    public EchoThread() {
        super();
    }
    public EchoThread(Socket accept) {
        super();
        this.accept = accept;
    }

    public void run() {
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            in = new DataInputStream(accept.getInputStream());
            out = new DataOutputStream(accept.getOutputStream());
            boolean goon = true;
            while (goon) {
                String str = in.readUTF();
                if (null == str || "".equals(str)) {
                    goon = false;
                } else {
                    if ("bye".equalsIgnoreCase(str)) {
                        goon = false;
                    } else {
                        out.writeUTF("ECHO:" + str);
                    }
                }
            }
            in.close();
            out.close();
            accept.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

        Class : EchoThreadServer

package limeNet.thread.server;

import java.net.ServerSocket;
import java.net.Socket;

public class EchoThreadServer {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);
        while(true){
            System.out.println("服务器运行,等待客户端连接。");
            Socket accept = serverSocket.accept();
            new Thread(new EchoThread(accept)).start();
        }
    }
}

        Class : EchoClient

package limeNet.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class EchoClient {

    public static void main(String[] args) throws Exception, Exception {
        Socket client = null;
        client = new Socket("localhost",8888);
        DataInputStream in = null;
        DataOutputStream out = null;
        in = new DataInputStream(client.getInputStream());
        out = new DataOutputStream(client.getOutputStream());
        Scanner sc = new Scanner(System.in);
        boolean flag = true;
        while(flag){
            System.out.print("输入信息:");
            String str = sc.nextLine();
            out.writeUTF(str);                                                                                                      
            if("bye".equals(str)){
                flag = false;
            }else{
                String echo = in.readUTF();
                System.out.println(echo);
            }
        }
        in.close();
        out.close();
        sc.close();
        client.close();
    }
}

    19.5 UDP程序设计

      19.5.1 UDP简介

      19.5.2 UDP程序实现

        Class : UDPClient

package limeNet.udp.client;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPClient {

    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(9000);
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, 1024);
//        阻塞
        ds.receive(dp);
        String str = new String(dp.getData(),0,dp.getLength()) + "from " + dp.getAddress().getHostAddress() + " : " + dp.getPort();
        System.out.println(str);
        ds.close();
    }
}

        Class : UDPServer

package limeNet.udp.server;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {

    public static void main(String[] args) throws IOException {
        DatagramSocket ds = null;
        DatagramPacket dp = null;
        ds = new DatagramSocket(3000);
        String str = "Hello World";
        dp = new DatagramPacket(str.getBytes(), str.length(),InetAddress.getByName("localhost"),9000);
        System.out.println("发送信息。");
        ds.send(dp);
        ds.close();
    }
}

啦啦啦

啦啦啦

啦啦啦

啦啦啦

啦啦啦

啦啦啦

啦啦啦

啦啦啦

posted @ 2017-01-19 13:38  limeOracle  阅读(342)  评论(0编辑  收藏  举报