Java网络编程

URL对象

  • URL类

    1. URL(Uniform Resource Locator)

      一致资源定位器的简称,表示Internet上某一资源的地址

    2. URL的组成

      protocol:resourceNamae

      协议名指明获取资源所使用的的传输协议,如http、ftp等,资源名则是资源的完整地址,包括主机名、端口号或文件内部的一个引用。

    3. 获取URL对象属性

      Public String getProtocol()
      
      Public String getHost()
      
      public String getPort()
      
      public String getFile()
      

URLConnection对象

  • 一个URLConnection对象代表一个URL资源与Java程序的通讯连接,可以通过它对这个URL资源读或写。

  • 与URL的区别

    1. URL是单向的,URLConnection是双向的

    2. 可以查看服务器的响应消息的首部

    3. 可以设置客户端请求消息的首部

  • 使用示例

    关键步骤:构造一个URL对象,调用URL对象的openConnection()方法获取对应该URL的URLConnection对象。

    public class URLConnector {
        public static void main(String[] args) {
            try {
                URL cs = new URL("http://www.sina.com/");
                URLConnection tc = cs.openConnection();
                BufferedReader in = new BufferedReader(new InputStreamReader(tc.getInputStream()));
                String inputLine;
                while((inputLine = in.readLine()) != null) {
                    System.out.println(inputLine);
                }
                in.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

Get与Post请求

  • 示例

    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" +param;
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while((line=in.readLine()) != null) {
                result += line;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    }
    
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setDoOutput(true);
            out = new PrintWriter(connection.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while((line=in.readLine()) != null) {
                result += line;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    }
    
  • HttpURLConnection类

    在URLConnection的基础上提供一系列针对http请求的内容

    1. HTTP状态码(例如HTTP_OK:200)
    2. setRequestMethod(设置请求方法GET\POST等)
    3. getResponseCode(获取HTTP的响应)

Socket通信原理

  • TCP传输协议(Transport Control Protocol)

    面向连接的能够提供可靠的流式数据传输的协议

    URL,URLConnection,Sokcet,ServerSocket等类都使用TCP协议进行网络通讯。

  • socket通讯

    网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个socket。

Socket通信实现

  • 创建socket

    使用Socket类构造

  • 客户端socket的建立

  • 服务端socket的建立

  • 打开输入输出流

  • 关闭socket

    注意先关闭流再关闭socket

    @TalkClient.java

    import java.net.*;
    import java.io.*;
    
    public class TalkClient {
        public static void main(String[] args) {
            System.out.println("Client Start...");
            try {
                Socket socket = new Socket("127.0.0.1", 8888);
                BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
                PrintWriter os = new PrintWriter(socket.getOutputStream());
                BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String readline;
                readline = sin.readLine();
                while (!readline.equals("bye")) {
                    os.println(readline);
                    os.flush();
                    System.out.println("Client:" + readline);
                    System.out.println("Server:" + is.readLine());
                    readline = sin.readLine();
                }
                os.close();
                is.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    @TalkServer.java

    public class TalkServer {
        public static void main (String[] args) {
            System.out.println("Server start...");
            try {
                ServerSocket server = new ServerSocket(8888);
                Socket socket = server.accept();
                String readline;
                BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter os = new PrintWriter(socket.getOutputStream());
                BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("Client: "+is.readLine());
                readline = sin.readLine();
                while (!readline.equals("bye")) {
                    os.println(readline);
                    os.flush();
                    System.out.println("Server:" + readline);
                    System.out.println("Client:" + is.readLine());
                    readline = sin.readLine();
                }
                os.close();
                is.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    注意os.print()与os.println()的区别,不要被回车符坑了!!!

Socket多客户端通信

@MultiTalkClient.java

public class MultiTalkClient {
    int num;
    public static void main(String[] args) {
        System.out.println("Client Start...");
        try {
            Socket socket = new Socket("127.0.0.1", 8888);

            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter os = new PrintWriter(socket.getOutputStream());
            BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            String readline;
            readline = sin.readLine();
            while (!readline.equals("bye")) {
                os.println(readline);
                os.flush();
                System.out.println("Client:" + readline);
                System.out.println("Server:" + is.readLine());
                readline = sin.readLine();
            }
            os.close();
            is.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@ServerThread.java

public class ServerThread extends Thread {
    Socket socket = null;
    int clientNum;

    public ServerThread(Socket socket, int num) {
        this.socket = socket;
        this.clientNum = num + 1;
    }

    @Override
    public void run() {
        try {
            String line;

            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter os = new PrintWriter(socket.getOutputStream());
            BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            System.out.println("Client"+clientNum+":"+is.readLine());
            line = sin.readLine();
            while (!line.equals("bye")) {
                os.println(line);
                os.flush();
                System.out.println("Server:" + line);
                System.out.println("Client"+clientNum+":"+is.readLine());
                line = sin.readLine();
            }
            os.close();
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@MultiTalkServer.java

public class MultiTalkServer {
    static int clientNum = 0;
    public static void main (String[] args) {
        System.out.println("Server start...");
        try {
            ServerSocket serverSocket = null;
            Boolean listening = true;
            try {
                serverSocket = new ServerSocket(8888);
            } catch (IOException e) {
                System.out.println("Could not listen on port:8888");
                System.exit(-1);
            }
            while (listening) {
                new ServerThread(serverSocket.accept(), clientNum).start();
                clientNum++;
            }
            serverSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

数据报通信

  • UDP(User Datagram Protocol)

    非面向连接的提供不可靠的数据包式的数据传输协议。

    DatagramPacket,DatagramSocket,MulticastSocket等类使用UDP协议进行网络通讯。

  • TCP(Transport Control Protocol)

    面向连接的能够提供可靠的流式数据传输的协议。

    URL,URLConnection,Socket,ServerSocket等类都使用TCP协议进行网络通讯。

  • 区别

    1. TCP有建立时间

    2. UDP传输有大小限制:64k以内

    3. TCP的应用:Telnet,ftp

    4. UDP的应用:ping

  • 使用数据报通信

    DatagramSocket()

    DatagramPacket()

  • 收数据报

    DatagramPacket packet = new DatagramPacket(buf,256);
    socket.recive(packet);
    
  • 发数据报

    DatagramPacket packet = new DatagramPacket(buf,buf.length,address,port);
    socket.send(packet);
    
  • 示例

    @QuoteClient.java

    public class QuoteClient {
        public static void main(String[] args) throws IOException {
            if (args.length != 1) {
                System.out.println("Usage:java QuoteClient <hostname>");
                return;
            }
    
            DatagramSocket socket = new DatagramSocket();
    
            //send request
            byte[] buf = new byte[256];
            InetAddress address = InetAddress.getByName(args[0]);
            DatagramPacket packet = new DatagramPacket(buf,buf.length,address,8888);
            socket.send(packet);
    
            //get response
            packet = new DatagramPacket(buf,buf.length);
            socket.receive(packet);
    
            //display response
            String received = new String(packet.getData());
            System.out.println("Quote of the Moment:"+received);
    
            socket.close();
        }
    }
    

    @QuoteServerThread.java

    public class QuoteServerThread extends Thread {
        protected DatagramSocket socket = null;
        protected BufferedReader in = null;
        protected boolean moreQuotes = true;
    
        public QuoteServerThread() throws SocketException {
            this("QuoteServerThread");
        }
    
        public QuoteServerThread(String name) throws SocketException {
            super(name);
            socket = new DatagramSocket(8888);
            try {
                in = new BufferedReader(new FileReader("one-liners.txt"));
            } catch (FileNotFoundException e) {
                System.err.println("Could not open quote file. Serving time instead.");
            }
        }
    
        @Override
        public void run() {
            while(moreQuotes) {
                try {
                    byte[] buf = new byte[256];
                    DatagramPacket packet = new DatagramPacket(buf,buf.length);
                    socket.receive(packet);
                    String dString = null;
                    if (in == null)
                        dString = new Date().toString();
                    else
                        dString = getNextQuote();
                    buf = dString.getBytes();
    
                    //send response
                    InetAddress address = packet.getAddress();
                    int port = packet.getPort();
                    packet = new DatagramPacket(buf,buf.length,address,port);
                    socket.send(packet);
                } catch (IOException e) {
                    e.printStackTrace();
                    moreQuotes = false;
                }
            }
            socket.close();
        }
    
        protected String getNextQuote() {
            String res = null;
            try {
                if ((res = in.readLine()) == null) {
                    in.close();
                    moreQuotes = false;
                    res = "No more quotes.";
                }
            } catch (IOException e) {
                res = "IOException occured in server";
            }
    
            return res;
        }
    }
    

    @QuoteServer.java

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

使用数据报进行广播通信

DatagramSocket只允许数据报发往一个目的地址

MulticastSocket将数据报以广播方式发送到该端口的所有客户

MulticastSocket用在客户端,监听服务器广播来的数据

  • 示例

    @MulticastClient.java

    public class MulticastClient {
        public static void main(String[] args) throws IOException {
            MulticastSocket socket = new MulticastSocket(4396);
            InetAddress address = InetAddress.getByName("230.0.0.1");
            socket.joinGroup(address);
            DatagramPacket packet;
    
            //get a few quotes
            for(int i=0;i<5;i++) {
                byte[] buf = new byte[256];
                packet = new DatagramPacket(buf,buf.length);
                socket.receive(packet);
                String received = new String(packet.getData());
                System.out.println("Quote of the Moment:"+received);
            }
            socket.leaveGroup(address);
            socket.close();
        }
    }
    

    @MulticastServerThread.java

    public class MulticastServerThread extends QuoteServerThread{
        private long FIVE_SECOND = 5000;
        public MulticastServerThread() throws IOException {
            super("MulticastServerThread");
        }
    
        @Override
        public void run() {
            while (moreQuotes) {
                try {
                    byte[] buf = new byte[256];
                    String dString = null;
                    if (in == null)
                        dString = new Date().toString();
                    else
                        dString = getNextQuote();
                    buf = dString.getBytes();
    
                    //send it
                    InetAddress group = InetAddress.getByName("230.0.0.1");
                    DatagramPacket packet = new DatagramPacket(buf,buf.length,group,4396);
                    socket.send(packet);
    
                    //sleep for a while
                    try {
                        sleep((long)(Math.random()*FIVE_SECOND));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    moreQuotes = false;
                }
            }
            socket.close();
        }
    }
    

    @MulticastServer.java

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

网络聊天程序

@ChatFrame.java

public class ChatFrame extends JFrame implements ActionListener {
    JTextField tf;
    JTextArea ta;
    JScrollPane sp;
    JButton send;
    JPanel p;

    int port;
    String s = "";
    String myID;
    Date date;
    ServerSocket server;
    Socket mySocket;
    BufferedReader is;
    PrintWriter os;
    String line;

    public ChatFrame(String ID,String remoteID,String IP,int port, boolean isServer) {
        super(ID);
        myID = ID;
        this.port = port;
        ta = new JTextArea();
        ta.setEditable(false);
        sp = new JScrollPane(ta);
        this.setSize(330,400);
        this.setResizable(false);

        try{
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.getContentPane().add(sp,"Center");
        p = new JPanel();
        this.getContentPane().add(p,"South");
        send = new JButton("发送");
        tf = new JTextField(20);
        tf.requestFocus();
        p.add(tf);
        p.add(send);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
        send.addActionListener(this);
        tf.addActionListener(this);

        if(isServer) {
            try {
                server = null;
                try {
                    server = new ServerSocket(port);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                mySocket = null;
                try {
                    mySocket = server.accept();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                is = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
                os = new PrintWriter(mySocket.getOutputStream());
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        else {
            try {
                mySocket = new Socket(IP,port);
                os = new PrintWriter(mySocket.getOutputStream());
                is = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        while (true) {
            try {
                line = is.readLine();
                date = new Date();
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String currentTime = formatter.format(date);
                s+=currentTime+" "+remoteID+"说:\n"+line+"\n";
                ta.setText(s);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = formatter.format(date);
        s+=currentTime+" "+myID+"说:\n"+tf.getText()+"\n";
        ta.setText(s);
        os.println(tf.getText());
        os.flush();
        tf.setText("");
        tf.requestFocus();
    }
}

@ChatServerFrame.java

public class ChatServerFrame {
    public static void main(String[] args) {
        ChatFrame cserver = new ChatFrame("Cat","Dog","localhost",4396,true);
    }
}

@ChatClientFrame.java

public class ChatClientFrame {
    public static void main(String[] args) {
        ChatFrame cclient = new ChatFrame("Dog","Cat","localhost",4396,false);
    }
}

实际运行如下图所示:

posted @ 2020-10-03 14:44  hunter-w  阅读(118)  评论(0编辑  收藏  举报