Java Socket与Linux Socket底层调用分析
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java Socket与Linux Socket底层调用分析,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4164字,纯文字阅读大概需要6分钟。
内容图文
![Java Socket与Linux Socket底层调用分析](/upload/InfoBanner/zyjiaocheng/945/f3bc7e7dc5cb4fbe9a895d86d2807712.jpg)
本文主要分析从Java Socket API到Linux Socket API的调用链,从而来探究Java Socket是如何利用Linux提供的系统调用来实现对应功能的。
Java Socket API示例代码
首先给出一个利用Java Socket API编写的简易的Hello/Hi代码示例。
//服务端
1 ServerSocket server = new ServerSocket(8000); 2 Socket client = server.accept(); 3 InputStream in = client.getInputStream(); 4 byte[] bytes = new byte[1024]; 5 int len = in.read(bytes); 6 String data = new String(bytes, 0 , len); 7 System.out.println("接收客户端消息:" + data); 8 9 OutputStream out = client.getOutputStream(); 10 out.write("Hi".getBytes()); 11 client.close();
//客户端
1 Socket client = new Socket("localhost", 8000); 2 OutputStream out = client.getOutputStream(); 3 String msg = "Hello"; 4 out.write(msg.getBytes()); 5 6 InputStream in = client.getInputStream(); 7 byte[] bytes = new byte[1024]; 8 int len = in.read(bytes); 9 String s = new String(bytes, 0, len); 10 System.out.println("接收服务端响应信息:" + s); 11 client.close();
服务端创建及接收连接
Socket服务端通过调用ServerSocket构造函数来进行创建并调用accept来接收客户端的连接请求。
创建
通过源码调试我们可以发现,在ServerSocket的构造函数中,调用了ServerSocket的bind方法。在bind方法中获取了AbstractPlainSocketImpl对象并调用了该对象两个重要的方法bind和listen。分别在AbstractPlainSocketImpl的bind和listen方法中,调用到了native方法socketBind和socketListen。为了搞清楚这两个native方法到底使用了哪些个Linux系统调用来实现功能,我们继续查阅了jdk中提供的native方法源码,在native/java/net/PlainSocketImpl.c中可以找到方法Java_java_net_PlainSocketImpl_socketBind和Java_java_net_PlainSocketImpl_socketListen。在方法Java_java_net_PlainSocketImpl_socketBind中可以清楚看到调用了NET_Bind来进行绑定,而NET_Bind实现在native/java/net/net_util_md.c,最终通过系统调用bind来进行绑定。在方法Java_java_net_PlainSocketImpl_socketListen中也可以看到调用了JVM_Listen来进行端口监听,而JVM_Listen实现在jvm.c,简单地调用了listen系统调用来进行监听。下图为服务端创建过程的大致调用流程。
连接接收
serverSocket调用accept来进行等待接收连接。其内部调用链与创建类似,即在implAccept方法调用过程中,获取了AbstractPlainSocketImpl对象并调用了该对象的accept方法,在AbstractPlainSocketImpl的accept方法中,进一步调用了native方法socketAccept。在native/java/net/PlainSocketImpl.c中可以找到该native方法的具体实现为Java_java_net_PlainSocketImpl_socketAccept,其中进一步调用了linux_close.c中的NET_Accept方法,并最终调用了系统调用accept来进行等待接收连接。
客户端创建
客户端的创建与服务端的创建相比较为简单。在Socket的构造函数中,如果我们指定了本地的InetAdress和localPort则会先调用bind方法来对指定端口进行绑定,具体bind过程与上述服务端bind过程类似。但是通常我们并不会客户端的本地地址进行指定,所以并不会执行bind过程,而是直接进行connect过程。在Socket的connect方法中,首先也会获取AbstractPlainSocketImpl对象并调用该对象的connect,然后调用到native方法socketConnect。按照上述的jdk native分析过程,我们可以查到socketConnect的调用链(括号外为方法,括号内为文件),Java_java_net_PlainSocketImpl_socketConnect(PlainSocketImpl.c)->NET_Select(linux_close.c)->select(sys_call)
数据读写
不管是客户端还是服务端都可能会需要进行数据的读写,其实现方式是相同的。
数据读
Java Socket直接通过获取SocketInputStream,调用read方法来进行数据读入。read方法进而调用了socketRead,在socketRead方法中又调用了native方法socketRead0。native方法socketRead0的实际实现为native/java/net/SocketInputStream.c中的Java_java_net_SocketInputStream_socketRead0,该方法继而又调用了linux_close.c中的NET_Read,最终调用了系统调用recv来进行数据读入。
数据写
Java Socket直接通过获取SocketOutputStream,调用write方法来进行数据写入。write方法进而调用了socketWrite,在socketWrite方法中又调用了native方法socketWrite0。native方法socketWrite0的实际实现为native/java/net/SocketOutputStream.c中的Java_java_net_SocketOutputStream_socketWrite0,该方法继而又调用了linux_close.c中的NET_Send,最终调用了系统调用send来进行数据写入。
关闭
当通讯双方通讯结束时,需要关闭socket。在Java代码中可以直接调用Socket的close来进行关闭。Socket的close方法会进一步调用AbstractPlainSocketImpl的close方法,继而调用native方法socketClose0。可在jdk提供的native源码中找到该native方法的调用链,Java_java_net_PlainSocketImpl_socketClose0(PlainSocketImpl.c)->NET_SocketClose(linux_close.c)->closefd(sys_call).
内容总结
以上是互联网集市为您收集整理的Java Socket与Linux Socket底层调用分析全部内容,希望文章能够帮你解决Java Socket与Linux Socket底层调用分析所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。