Java之网络编程

2018-09-13  本文已影响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();

            }

        }

    }

}

上一篇下一篇

猜你喜欢

热点阅读