美文网首页
Java之网络编程

Java之网络编程

作者: 如果仲有听日 | 来源:发表于2018-09-13 10:40 被阅读0次

    InetAddress

    DatagramPacket、DatagramSocket

    ServerSocket、Socket

    SocketAddress -> InetSocketAddress


    1. InetAddress

    jdk手册中发现没有构造方法,说明构造方法是私有的,也就是说我们只能用它的static静态方法去获取InetAddress的对象,再使用非静态方法

    常用方法:

        静态:

            static InetAddress getLocalHost() //能够返回当前主机InetAddress类的对象

            static InetAddress getByName(String host) //返回指定主机名的InetAddress类的对象

        非静态:

            String getHostName()    //获取主机名

            String getHostAddress()    //获取主机IP地址

    获取本机IP地址和主机名 获取指定主机名的IP地址和主机名

    2. UDP协议收发数据

    DatagramPacket:包装原始数据为socket数据包

    DatagramSocket:发送包装好的socket数据包

    2.1. UDP发送端

    流程:

        创建DatagramPacket对象,封装数据,接收的ip和port(在构造方法中传所有参数)

        创建DatagramSocket

        调用DatagramSocket类的方法send,发送数据包

        关闭资源DatagramSocket类

    udp发送端

    2.2. UDP接收端

    流程:

        创建DatagramSocket,bind port,收发port要相同

        闯进byte数组,接收发送端发送过来的数据包

        创建数据包对象DatagramPacket

        调用DatagramSocket对象的阻塞接收方法receive()

        拆包,能够获取到发送过来包的length、IP地址、数据。

        关闭资源

    udp接收端

    3. TCP协议收发数据

    3.1. 简单的TCP客户端、服务器端

    先运行服务器端,等待客户端连接,再运行client

    client向server发送消息,server收到后再回给client消息

    客户端代码 服务器端代码

    服务器端的核心在于,通过accept拿到客户端的连接Socket,进而获得读取数据的InputStream对象和写数据的OutputStream对象

    3.2. TCP实现文件上传

    先运行服务器端,再等待客户端连接

    客户端代码 服务器端代码

    运行后发现,server和client都卡住了,主要是服务器端卡在while((len = is.read(b)) != -1)这里,一直阻塞

    原因是,服务器端并不知道client传输过来的数据包什么时候结束,因此需要修改客户端,告知服务器端什么时候该停止接收数据

    Socket中有一个方法:public void shutdownOutput()

    这个方法就是客户端用于告知服务器端,我的OutputStream在什么点应该结束,这个是方法中自己定一个一个结束标识符,不用关心是什么,只要调用它,服务器端就知道什么点该退出阻塞read了。

    修改后的client端代码

    3.3. 大文件多线程上传

    这里做一个对比,如果用单线程上例传输一个1G的大文件,经过反复测试,耗时大约17~18s

    现在改为用多线程传输:

    有空再做

    3.4. Socket远程调用示例

    这个demo可以在服务器端接收客户端的数据,并用反射或者动态代理来完成远程过程调用

    反射和动态代理见:https://www.jianshu.com/p/0d0c13b92e04

    代码:

    程序结构

    public class ServerRunnable implements Runnable{

        Socket socket = null;

        InputStream in = null;

        OutputStream out = null;

        public ServerRunnable(Socket socket) {

            this.socket = socket;

        }

        @Override

        public void run() {

            try {

                in = socket.getInputStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(in));

                String param = br.readLine();

                /**

                * this place can be using reflect to do something

                */

                GetDataServiceImpl getDataServiceImpl = new GetDataServiceImpl();

                String result = getDataServiceImpl.getData(param);

                out = socket.getOutputStream();

                PrintWriter pw = new PrintWriter(out);

                pw.println(result);

                pw.flush();

            } catch (IOException e) {

                e.printStackTrace();

            }finally{

                try {

                    in.close();

                    out.close();

                    socket.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

    }

    相关文章

      网友评论

          本文标题:Java之网络编程

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