Java Socket应用

作者: 有苦向瓜诉说 | 来源:发表于2017-09-26 16:19 被阅读92次

    网络基础

    1. 端口号范围0-65535,系统保留0-1023,常见端口http:80,ftp:21,telnet:23
    2. socket=ip+端口
    3. java主要分为InetAdress,URL,Socket(TCP),DatagramSocket(UDP)等类

    InetAddress类

    InetAddress类没有构造方法,可以通过静态方法获取InetAddress实例对象。

    1. 获取本地主机:getLocalHost()
    2. 通过主机名获取实例:getByName(String Host)
    3. 对实例操作:getHostName()获取主机名,getHostAddress()获取主机ip地址,getAddress()以字节数组的形式返回ip地址

    测试:

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.Arrays;
    
    public class Test{
        public static void main(String[] args) throws UnknownHostException{
            //获取本机名
            InetAddress address=InetAddress.getLocalHost();
            System.out.println(address.getHostName());//输出主机名
            System.out.println(address.getHostAddress());//输出主机ip地址
            byte[] bytes=address.getAddress(); //用字节数组表示ip地址
            System.out.println(Arrays.toString(bytes));
            //通过主机名获取
            InetAddress address2=InetAddress.getByName("你们的大神");//通过名字获取,name可为主机名或者ip地址
            //InetAddress address2=InetAddress.getByName("baidu.com");
            //InetAddress address2=InetAddress.getByName("192.168.0.109");
            System.out.println(address2.getHostName());
            System.out.println(address2.getHostAddress());
            byte[] bytes2=address2.getAddress();
            System.out.println(Arrays.toString(bytes2));
        }
    }
    

    URL类

    常用构造方法:
    1. URL(String spec)
    2. URL(String protocol, String host, int port,String file)
    3. URL(URL context, String spec) 通过已存在的URL构建
    常用get方法:

    getRef()获取锚点,getQuery()获取查询字符串,getPort()获取端口号(未指定默认为-1,而浏览器默认为80),其他的见测试用例。

    测试:

    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class Test {
        public static void main(String[] args) throws MalformedURLException {
            URL imooc = new URL("http://www.imooc.com"); // 直接创建
            URL url = new URL(imooc, "/index.html?username=tom#test");// 根据已存在的创建,?表示参数,#表示锚点
            System.out.println(url.getProtocol());
            System.out.println(url.getHost());
            System.out.println(url.getPort()); //如未指定,则返回-1;
            System.out.println(url.getPath());
            System.out.println(url.getFile());
            System.out.println(url.getRef()); //锚点
            System.out.println(url.getQuery()); //查询字符串
        }
    }
    
    结果:
    http
    www.imooc.com
    -1
    /index.html
    /index.html?username=tom
    test
    username=tom
    
    获取页面内容

    使用openStream()获取字节输入流。
    测试:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.URL;
    
    //通过URL获取页面内容
    public class Test {
        public static void main(String[] args) throws IOException {
            URL url=new URL("http://www.baidu.com");
            InputStream is=url.openStream();//使用openStream获取字节输入流
            InputStreamReader isr=new InputStreamReader(is,"utf-8");//在字节到字符流时需要指定编码方式,避免乱码
            BufferedReader br=new BufferedReader(isr); //添加缓冲流
            
            String data=br.readLine();
            while (data!=null){
                System.out.println(data);
                data=br.readLine();
            }
        }
    }
    

    Socket TCP通信

    流程

    创建ServerSocket和Socket,打开输入输出流,进行操作读写操作,关闭输入输出流,关闭socket。

    具体
    1. ServerServer类是服务端socket,侦听客户端的请求。
      常用构造:ServerSocket(int port)
      常用实例方法:accept(),close(),getInetAddress(),getPort()
    2. Socket类是通信的端点。
      常用构造:Socket(InetAddress address,int port)或Socket(String host,int port)
      常用实例方法:getInetAddress(),close()
      getInputStream(),getOutputStream(),shutdownInput(),shutdownOutput()
    3. 多线程服务器,可以接受多个客户端的请求,创建一个线程类,完成对客户端的操作。
    测试

    Server.java (服务器)

    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server {
    
        public static void main(String[] args) throws IOException {
            // 1.创建服务器ServerSocket,绑定端口
            ServerSocket serverSocket = new ServerSocket(8888);
            // 2.使用accept侦听,侦听来自客户端的连接
            System.out.println("****服务器正在启动,侦听连接****");
            int count=0;
            Socket socket;
            while (true) {
                socket = serverSocket.accept();
                ServerThread serverThread = new ServerThread(socket);
                serverThread.start();
                count++;
                System.out.println("client number:"+count);
                InetAddress address=socket.getInetAddress();
                System.out.println("client address:"+address.getHostAddress());
            }
            // serverSocket.close();不会执行到这一步,一直循环,去掉该语句。    
        }
    }
    
    

    ServerThread.java (服务器线程)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    public class ServerThread extends Thread {
        Socket socket = null;
    
        public ServerThread(Socket socket) {
            this.socket = socket;
        }
    
        public void run() {
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            OutputStream os = null;
            PrintWriter pw = null;
            try {
                is = socket.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr); // 添加缓冲流
                String data = null;
                while ((data = br.readLine()) != null) {
                    System.out.println("我是服务端,客户端说:" + data);
                }
                socket.shutdownInput(); // 关闭socket的输入流
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write("hello");
                pw.flush();
                socket.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (pw != null)
                        pw.close();
                    if (os != null)
                        os.close();
                    if (br != null)
                        br.close();
                    if (isr != null)
                        isr.close();
                    if (is != null)
                        is.close();
                    if (socket != null)
                        socket.close();
                } catch (IOException e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }
    
            }
    
        }
    }
    

    Client.java (客户端)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class Client {
        public static void main(String[] args) throws UnknownHostException, IOException {
            //1.创建客户端socket,指定服务器地址和端口
            Socket socket=new Socket("localhost", 8888);//本地服务器的8888端口
            //2. 获取输出流,发送信息
            OutputStream os=socket.getOutputStream();
            PrintWriter pw=new PrintWriter(os);
            pw.write("admin:456");
            pw.flush();
            socket.shutdownOutput();
            // 3. 获取输入流,接收信息
            InputStream is=socket.getInputStream();
            InputStreamReader isr=new InputStreamReader(is);
            BufferedReader br=new BufferedReader(isr); //添加缓冲流
            String  data=null;
            while((data=br.readLine())!=null){
                System.out.println("我是客户端,服务端说:"+data);
            }
            socket.shutdownInput(); //关闭socket的输入流  
            //3.关闭资源
            is.close();
            isr.close();
            br.close();
            pw.close();
            os.close();
            socket.close();
        }
    }
    

    Socket UDP通信

    流程

    客户端和服务器创建DatagramPacket保存相应数据,创建DatagramSocket,使用DatagramSocket实例的send(),receive()方法来进行通信

    具体
    1. DatagramPacket类是UDP用来发送的数据报,UDP无连接,所以数据中可以包含ip地址,端口号等。另外,需要另外定义一个byte[]类型的数组,用来存放数据,这个数组与DatagramPacket实例实质上是同一个。
    2. DatagramSocket类是用来发送或者接受数据报的,主要使用该实例的receive(DatagramPacket packet)和send(DatagramPacket packet)方法,分别把数据存放在packet中的数组中(自己另外定义的),以及相关信息。
    3. 也可以用多线程服务器。
    测试

    UDPserver.java(UDP服务器)

    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 {
            // 1. 创建服务器端datagramsocket,指定端口
            DatagramSocket socket = new DatagramSocket(8800);
            // 2. 创建数据报,用于接受客户端发送的数据
            byte[] data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data, 0, data.length);
            // 3.接受客户端发送的数据,存放在packet
            System.out.println("***服务器正在启动***");
            socket.receive(packet);
            // 4.读取数据
            String info = new String(data, 0, packet.getLength());
            System.out.println("i'm server,client say:" + info);
    
            // 数据,发送至客户端
            // 1.得到客户端地址,端口,数据
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            byte[] data2 = "hello".getBytes();
            // 2.创建数据报
            DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
            // 3.响应客户端
            socket.send(packet2);
            // 4.关闭资源
            socket.close();
        }
    }
    

    UDPclient(客户端)

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPClient {
        public static void main(String[] args) throws IOException {
            // 1.定义服务器的地址,端口,数据
            InetAddress address = InetAddress.getByName("localhost");
            int port = 8800;
            byte[] data = "admin:123".getBytes();
            // 2.创建数据报,包含信息
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            // 3.创建DatagramSocket对象
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);
    
            // 接受来自服务器数据
            byte[] data2 = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(data2, 0, data2.length);
            // 3.接受客户端发送的数据,存放在packet
            socket.receive(packet2);
            // 4.读取数据
            String info = new String(data2, 0, packet2.getLength());
            System.out.println("i'm client,server say:" + info);
        }
    }
    

    相关文章

      网友评论

        本文标题:Java Socket应用

        本文链接:https://www.haomeiwen.com/subject/dxxsextx.html