Java登陆第十二天——网络编程(二)InetAddress、Socket

发布时间 2023-11-23 20:46:06作者: ocraft

Java提供了java.net包,专门用来进行网络开发。

InetAddress

InetAddress类主要表示IP地址。InetAddress类常用方法如下:

方法 类型 描述
public static InetAddress getByName(String host) throws UnknownHostException 静态方法 根据域名/主机名得到InetAddress对象
public static InetAddress getLocalHost() throws UnknownHostException 静态方法 获取本机的InetAddress对象
public String getHostName() 普通方法 获取主机名
public String getHostAddress() 普通方法 获取IP地址
public boolean isReachable(int timeout) throws IOException 普通方法 判断地址是否可以访问,并传入超时时间

栗子:测试InetAddress类常用方法

代码如下:

    public static void main(String[] args) {
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            System.out.println("本机InetAddress对象信息:"+localHost);
            System.out.println("本机主机名:"+localHost.getHostName());//因为InetAddress构造方法私有化
            System.out.println("本机IP地址:"+localHost.getHostAddress());//所以只能通过这种方式调用其普通方法

            InetAddress byName = InetAddress.getByName("www.bilibili.com");//通过域名获取InetAddress对象
            System.out.println("是否可以访问:"+byName.isReachable(5000));//ms为单位 5000ms=5s

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

程序运行结果:

本机InetAddress对象信息:DESKTOP-Q99QTUH/172.220.44.93
本机主机名:DESKTOP-Q99QTUH
本机IP地址:172.220.44.93
是否可以访问:true

之前域名说过,localhost是一个特殊的域名。

栗子:测试localhost特殊域名

代码如下:

    public static void main(String[] args) {
        try {
            InetAddress localhost = InetAddress.getByName("localhost");
            System.out.println(localhost);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

程序运行结果:

localhost/127.0.0.1

Socket

使用Socket(套接字)可以进行TCP程序的开发,此类可以建立双向地、可靠地、持续地通信连接。

服务端使用ServerSocket类等待客户端连接。每一个客户端都是一个Socket对象。
image

ServerSocket

ServerSocket类主要是编写服务端程序,用于接收客户端请求。常用方法如下:

方法 类型 描述
public ServerSocket(int port) throws IOException 构造方法 监听指定端口
public Socket accept() throws IOException 普通方法 等待客户端请求并返回Socket对象(没有会一直阻塞)
public InetAddress getInetAddress() 普通方法 返回服务器IP地址
public void close() throws IOException 普通方法 关闭服务端

栗子:编写一个本机的服务端,端口为8888

服务端,Test24server类::

//服务端,Test24server类
    public static void main(String[] args) {
        try {

            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("成功创建服务端对象,接下来监听8888端口");
            serverSocket.accept();
            //若无客户端访问8888端口,程序就会阻塞在此;若有客户端访问8888端口,创建并返回一个Socket对象。

            System.out.println("1");//若执行到此证明不会阻塞
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

程序运行结果:

成功创建服务端对象,接下来监听8888端口
//阻塞中....

服务端每次运行时都会调用accept()方法等待客户端连接,此方法会一直阻塞,直到客户端连接之后程序才会继续向下执行。该方法返回值是一个Socket对象。

Socket

每一个Socket对象都代表一个客户端对象。Socket类常用方法如下:

方法 类型 描述
public Socket(String host, int port, InetAddress localAddr,int localPort) throws IOException 构造方法 连接服务端的主机名及端口
public OutputStream getOutputStream() throws IOException 普通方法 获取该客户端的输出流
public void shutdownOutput() throws IOException 普通方法 输出结束
public InputStream getInputStream() throws IOException 普通方法 获取该客户端的输入流
public void shutdownInput() throws IOException 普通方法 输入结束

栗子:继续使用服务端栗子,客户端连接至服务端。

服务端,Test24server类:

//服务端,Test24server类
public class Test24server {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("成功创建服务端对象,接下来监听8888端口");
            serverSocket.accept();
            //若无客户端访问8888端口,程序就会阻塞在此;若有客户端访问8888端口,创建并返回一个Socket对象。

            System.out.println("1");//若执行到此证明不会阻塞
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端,Test24client类:

//客户端,Test24client类
public class Test24client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 8888);//访问本机8888端口
            System.out.println("连接服务端成功,啥事不干只连接");
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

程序运行结果:
image

栗子:客户端访问本机8888端口,并输出hello,world
服务端利用accpet()方法返回的Socket对象读取内容

客户端,Test24client类:

//客户端,Test24client类
public class Test24client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 8888);
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());//字节、字符输出都可以
            writer.write("hello,world");
            writer.flush();//一定要手动提交缓冲区内容!!!
            socket.shutdownOutput();//告诉服务端输出完毕,不用继续等待了。一定一定一定!!!

            writer.close();//资源类一定要使用后就关闭!
            socket.close();
            System.out.println("1");//证明运行到此
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端,Test24server类:

//服务端,Test24server类
public class Test24server {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("服务端启动成功,监听8888端口");
            Socket socket = serverSocket.accept();//获取客户端的Socket对象

            InputStreamReader reader = new InputStreamReader(socket.getInputStream());//什么流输出什么流读取
            char[] chars = new char[1024];
            int i;
            while ( (i = reader.read(chars) ) !=-1 ){
                System.out.println(new String(chars,0,i));
            }
            socket.shutdownInput();//读取完毕

            reader.close();
            serverSocket.close();

            System.out.println("1");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

程序运行结果:
image

栗子:客户端给本机服务端8888发送一张图片
服务端接收到图片后,回复"收到图片"
客户端接收服务端回复的消息
退出

客户端,Test24client类:

//客户端,Test24client类
public class Test24client {
    public static void main(String[] args) {
        File file = new File("D:\\IOtest\\finger.jpg");
        try {
            Socket socket = new Socket("localhost", 8888);
            System.out.println("发送图片");

            BufferedOutputStream socketOut = new BufferedOutputStream(socket.getOutputStream());
            FileInputStream filein = new FileInputStream(file);

            int i;
            byte[] bytes = new byte[1024];
            while ( (i=filein.read(bytes))!=-1 ){//文件流读取,socket输出流输出
                socketOut.write(bytes,0,i);
                socketOut.flush();
            }
            socket.shutdownOutput();//输出结束

            BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());//服务端接收到图片后,会发送消息
            while ( (i=inputStream.read(bytes))!=-1 ){//文件流读取,socket输出流输出
                System.out.println(new String(bytes,0,i));
            }
            socket.shutdownInput();//输出结束

            inputStream.close();//后开启的先关闭
            filein.close();
            socketOut.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端,Test24server类:

//服务端,Test24server类
public class Test24server {
    public static void main(String[] args){
        File file = new File("D:\\Code\\Maven\\src\\main\\resources\\finger.jpg");
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket socket = serverSocket.accept();

            System.out.println("接收图片");

            BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
            FileOutputStream fileout = new FileOutputStream(file);
            int i;
            byte[] bytes = new byte[1024];
            while ( (i=inputStream.read(bytes))!=-1 ){//socket输入流读取,文件流输出
                fileout.write(bytes,0,i);
            }
            socket.shutdownInput();//输入结束

            BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
            outputStream.write("收到图片".getBytes());//返回消息
            outputStream.flush();//一定要刷新!!
            socket.shutdownOutput();//输出结束


            outputStream.close();//后开启的先关闭
            fileout.close();
            inputStream.close();
            socket.close();
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

程序运行结果:
image