一、Socket类

Socket 类表示通信双方中的客户端,用于呼叫远端机器上的一个端口,主动向服务器端发送数据(当连接建立后也能接收数据)。下面我将从源码的角度来介绍Socket类的内部原理及其方法。

二、Socket类源码介绍

首先,Socket类实现了java.io.Closeable的接口

public
class Socket implements java.io.Closeable {}

下面定义了一些Socket的一些状态

    private boolean created = false;private boolean bound = false;private boolean connected = false;private boolean closed = false;private Object closeLock = new Object();private boolean shutIn = false;private boolean shutOut = false;

Socket 的实现

SocketImpl impl;

确定是否使用旧的 Socket

private boolean oldImpl = false;

创建一个未连接的Socket

public Socket() {setImpl();}

Socket 的实现类,通过Proxy代理实现

public Socket(Proxy proxy) {// Create a copy of Proxy as a security measureif (proxy == null) {throw new IllegalArgumentException("Invalid Proxy");}Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY: sun.net.ApplicationProxy.create(proxy);Proxy.Type type = p.type();if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) {SecurityManager security = System.getSecurityManager();InetSocketAddress epoint = (InetSocketAddress) p.address();if (epoint.getAddress() != null) {checkAddress (epoint.getAddress(), "Socket");}if (security != null) {if (epoint.isUnresolved())epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());if (epoint.isUnresolved())security.checkConnect(epoint.getHostName(), epoint.getPort());elsesecurity.checkConnect(epoint.getAddress().getHostAddress(),epoint.getPort());}impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p): new HttpConnectSocketImpl(p);impl.setSocket(this);} else {if (p == Proxy.NO_PROXY) {if (factory == null) {impl = new PlainSocketImpl();impl.setSocket(this);} elsesetImpl();} elsethrow new IllegalArgumentException("Invalid Proxy");}}

使用用户指定的 SocketImpl 创建一个未连接的 Socket。

protected Socket(SocketImpl impl) throws SocketException {this.impl = impl;if (impl != null) {checkOldImpl();this.impl.setSocket(this);}}

Socket使用代理器和端口号篇port

public Socket(String host, int port)throws UnknownHostException, IOException{this(host != null ? new InetSocketAddress(host, port) :new InetSocketAddress(InetAddress.getByName(null), port),(SocketAddress) null, true);}

利用网络地址和端口号创建Socket

public Socket(InetAddress address, int port) throws IOException {this(address != null ? new InetSocketAddress(address, port) : null,(SocketAddress) null, true);}

创建本地和联网的Socket

public Socket(String host, int port, InetAddress localAddr,int localPort) throws IOException {this(host != null ? new InetSocketAddress(host, port) :new InetSocketAddress(InetAddress.getByName(null), port),new InetSocketAddress(localAddr, localPort), true);}
public Socket(InetAddress address, int port, InetAddress localAddr,int localPort) throws IOException {this(address != null ? new InetSocketAddress(address, port) : null,new InetSocketAddress(localAddr, localPort), true);}

定义实现本地连接和本地数据流

private Socket(SocketAddress address, SocketAddress localAddr,boolean stream) throws IOException {setImpl();// backward compatibilityif (address == null)throw new NullPointerException();try {createImpl(stream);if (localAddr != null)bind(localAddr);connect(address);} catch (IOException | IllegalArgumentException | SecurityException e) {try {close();} catch (IOException ce) {e.addSuppressed(ce);}throw e;}}

创建套接字实现。

void createImpl(boolean stream) throws SocketException {if (impl == null)setImpl();try {impl.create(stream);created = true;} catch (IOException e) {throw new SocketException(e.getMessage());}}

检查旧的嵌套字

private void checkOldImpl() {if (impl == null)return;// SocketImpl.connect() is a protected method, therefore we need to use// getDeclaredMethod, therefore we need permission to access the memberoldImpl = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {public Boolean run() {Class<?> clazz = impl.getClass();while (true) {try {clazz.getDeclaredMethod("connect", SocketAddress.class, int.class);return Boolean.FALSE;} catch (NoSuchMethodException e) {clazz = clazz.getSuperclass();// java.net.SocketImpl class will always have this abstract method.// If we have not found it by now in the hierarchy then it does not// exist, we are an old style impl.if (clazz.equals(java.net.SocketImpl.class)) {return Boolean.TRUE;}}}}});}

设置网络嵌套字

void setImpl() {if (factory != null) {impl = factory.createSocketImpl();checkOldImpl();} else {// No need to do a checkOldImpl() here, we know it's an up to date// SocketImpl!impl = new SocksSocketImpl();}if (impl != null)impl.setSocket(this);}

获取网络嵌套字

SocketImpl getImpl() throws SocketException {if (!created)createImpl(true);return impl;}

定义连接服务端

public void connect(SocketAddress endpoint) throws IOException {connect(endpoint, 0);}

定义连接并设置有超时时间

 public void connect(SocketAddress endpoint, int timeout) throws IOException {if (endpoint == null)throw new IllegalArgumentException("connect: The address can't be null");if (timeout < 0)throw new IllegalArgumentException("connect: timeout can't be negative");if (isClosed())throw new SocketException("Socket is closed");if (!oldImpl && isConnected())throw new SocketException("already connected");if (!(endpoint instanceof InetSocketAddress))throw new IllegalArgumentException("Unsupported address type");InetSocketAddress epoint = (InetSocketAddress) endpoint;InetAddress addr = epoint.getAddress ();int port = epoint.getPort();checkAddress(addr, "connect");SecurityManager security = System.getSecurityManager();if (security != null) {if (epoint.isUnresolved())security.checkConnect(epoint.getHostName(), port);elsesecurity.checkConnect(addr.getHostAddress(), port);}if (!created)createImpl(true);if (!oldImpl)impl.connect(epoint, timeout);else if (timeout == 0) {if (epoint.isUnresolved())impl.connect(addr.getHostName(), port);elseimpl.connect(addr, port);} elsethrow new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");connected = true;/** If the socket was not bound before the connect, it is now because* the kernel will have picked an ephemeral port & a local address*/bound = true;}

将嵌套字绑定本地

public void bind(SocketAddress bindpoint) throws IOException {if (isClosed())throw new SocketException("Socket is closed");if (!oldImpl && isBound())throw new SocketException("Already bound");if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))throw new IllegalArgumentException("Unsupported address type");InetSocketAddress epoint = (InetSocketAddress) bindpoint;if (epoint != null && epoint.isUnresolved())throw new SocketException("Unresolved address");if (epoint == null) {epoint = new InetSocketAddress(0);}InetAddress addr = epoint.getAddress();int port = epoint.getPort();checkAddress (addr, "bind");SecurityManager security = System.getSecurityManager();if (security != null) {security.checkListen(port);}getImpl().bind (addr, port);bound = true;}

检查地址

private void checkAddress (InetAddress addr, String op) {if (addr == null) {return;}if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {throw new IllegalArgumentException(op + ": invalid address type");}}

定义接受请求

final void postAccept() {connected = true;created = true;bound = true;}

下面定义实现状态设置

void setCreated() {created = true;}void setBound() {bound = true;}void setConnected() {connected = true;}

获取网络地址

public InetAddress getInetAddress() {if (!isConnected())return null;try {return getImpl().getInetAddress();} catch (SocketException e) {}return null;}

获取本地地址

public InetAddress getLocalAddress() {// This is for backward compatibilityif (!isBound())return InetAddress.anyLocalAddress();InetAddress in = null;try {in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);SecurityManager sm = System.getSecurityManager();if (sm != null)sm.checkConnect(in.getHostAddress(), -1);if (in.isAnyLocalAddress()) {in = InetAddress.anyLocalAddress();}} catch (SecurityException e) {in = InetAddress.getLoopbackAddress();} catch (Exception e) {in = InetAddress.anyLocalAddress(); // "0.0.0.0"}return in;}

返回此套接字连接到的远程端口号。

public int getPort() {if (!isConnected())return 0;try {return getImpl().getPort();} catch (SocketException e) {// Shouldn't happen as we're connected}return -1;}

获取本地端口号

 public int getLocalPort() {if (!isBound())return -1;try {return getImpl().getLocalPort();} catch(SocketException e) {// shouldn't happen as we're bound}return -1;}

获取远程嵌套字地址

public SocketAddress getRemoteSocketAddress() {if (!isConnected())return null;return new InetSocketAddress(getInetAddress(), getPort());}

获取本地嵌套字地址

public SocketAddress getLocalSocketAddress() {if (!isBound())return null;return new InetSocketAddress(getLocalAddress(), getLocalPort());}

获取嵌套字的传输管道

public SocketChannel getChannel() {return null;}

获取输入流函数

public InputStream getInputStream() throws IOException {if (isClosed())throw new SocketException("Socket is closed");if (!isConnected())throw new SocketException("Socket is not connected");if (isInputShutdown())throw new SocketException("Socket input is shutdown");final Socket s = this;InputStream is = null;try {is = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {public InputStream run() throws IOException {return impl.getInputStream();}});} catch (java.security.PrivilegedActionException e) {throw (IOException) e.getException();}return is;}

获取输出流函数

 public OutputStream getOutputStream() throws IOException {if (isClosed())throw new SocketException("Socket is closed");if (!isConnected())throw new SocketException("Socket is not connected");if (isOutputShutdown())throw new SocketException("Socket output is shutdown");final Socket s = this;OutputStream os = null;try {os = AccessController.doPrivileged(new PrivilegedExceptionAction<OutputStream>() {public OutputStream run() throws IOException {return impl.getOutputStream();}});} catch (java.security.PrivilegedActionException e) {throw (IOException) e.getException();}return os;}

设置无延时TCP传输

public void setTcpNoDelay(boolean on) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));}

获取TCP无延时服务

public boolean getTcpNoDelay() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");return ((Boolean) getImpl().getOption(SocketOptions.TCP_NODELAY)).booleanValue();}

设置延时等待

public void setSoLinger(boolean on, int linger) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");if (!on) {getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on));} else {if (linger < 0) {throw new IllegalArgumentException("invalid value for SO_LINGER");}if (linger > 65535)linger = 65535;getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));}}

获取延时等待

public int getSoLinger() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");Object o = getImpl().getOption(SocketOptions.SO_LINGER);if (o instanceof Integer) {return ((Integer) o).intValue();} else {return -1;}}

发送紧急信息

public void sendUrgentData (int data) throws IOException  {if (!getImpl().supportsUrgentData ()) {throw new SocketException ("Urgent data not supported");}getImpl().sendUrgentData (data);}

设置OOB内联

public void setOOBInline(boolean on) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));}

获取OOB(面向对象)内联

public boolean getOOBInline() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");return ((Boolean) getImpl().getOption(SocketOptions.SO_OOBINLINE)).booleanValue();}

设置超时时间

public synchronized void setSoTimeout(int timeout) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");if (timeout < 0)throw new IllegalArgumentException("timeout can't be negative");getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));}

获取超时时间

public synchronized int getSoTimeout() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);/* extra type safety */if (o instanceof Integer) {return ((Integer) o).intValue();} else {return 0;}}

设置发送缓冲区大小

public synchronized void setSendBufferSize(int size)throws SocketException{if (!(size > 0)) {throw new IllegalArgumentException("negative send size");}if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));}

获取发送缓冲区大小

public synchronized int getSendBufferSize() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");int result = 0;Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);if (o instanceof Integer) {result = ((Integer)o).intValue();}return result;}

设置获取缓冲区的大小

 public synchronized void setReceiveBufferSize(int size)throws SocketException{if (size <= 0) {throw new IllegalArgumentException("invalid receive size");}if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));}

获取获取缓冲区大小

public synchronized int getReceiveBufferSize()throws SocketException{if (isClosed())throw new SocketException("Socket is closed");int result = 0;Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);if (o instanceof Integer) {result = ((Integer)o).intValue();}return result;}

设置保持存活函数

public void setKeepAlive(boolean on) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));}

获取保持存活函数

public boolean getKeepAlive() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");return ((Boolean) getImpl().getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();}

设置Socket传输通道大小

public void setTrafficClass(int tc) throws SocketException {if (tc < 0 || tc > 255)throw new IllegalArgumentException("tc is not in range 0 -- 255");if (isClosed())throw new SocketException("Socket is closed");try {getImpl().setOption(SocketOptions.IP_TOS, tc);} catch (SocketException se) {// not supported if socket already connected// Solaris returns error in such casesif(!isConnected())throw se;}}

获取Socket传输通道大小

public int getTrafficClass() throws SocketException {return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS))).intValue();}

定义设置重用地址方法

public void setReuseAddress(boolean on) throws SocketException {if (isClosed())throw new SocketException("Socket is closed");getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));}

定义获取重用方法

public boolean getReuseAddress() throws SocketException {if (isClosed())throw new SocketException("Socket is closed");return ((Boolean) (getImpl().getOption(SocketOptions.SO_REUSEADDR))).booleanValue();}

定义Socket类的关闭

public synchronized void close() throws IOException {synchronized(closeLock) {if (isClosed())return;if (created)impl.close();closed = true;}}

这个方法应放置于文件末尾,用于关闭嵌套字的输入

 public void shutdownInput() throws IOException{if (isClosed())throw new SocketException("Socket is closed");if (!isConnected())throw new SocketException("Socket is not connected");if (isInputShutdown())throw new SocketException("Socket input is already shutdown");getImpl().shutdownInput();shutIn = true;}

这个方法应放置于文件末尾,用于关闭嵌套字的输出

public void shutdownOutput() throws IOException{if (isClosed())throw new SocketException("Socket is closed");if (!isConnected())throw new SocketException("Socket is not connected");if (isOutputShutdown())throw new SocketException("Socket output is already shutdown");getImpl().shutdownOutput();shutOut = true;}

将Socket信息转化为字符串

public String toString() {try {if (isConnected())return "Socket[addr=" + getImpl().getInetAddress() +",port=" + getImpl().getPort() +",localport=" + getImpl().getLocalPort() + "]";} catch (SocketException e) {}return "Socket[unconnected]";}

判断是否处于连接状态

public boolean isConnected() {// Before 1.3 Sockets were always connected during creationreturn connected || oldImpl;}

判断是否处于绑定状态

public boolean isBound() {// Before 1.3 Sockets were always bound during creationreturn bound || oldImpl;}

判断是否关闭状态

public boolean isClosed() {synchronized(closeLock) {return closed;}}

判断是否是输入关闭状态

public boolean isInputShutdown() {return shutIn;}

判断是否是输出关闭状态

public boolean isOutputShutdown() {return shutOut;}

定义所有客户端套接字的工厂

private static SocketImplFactory factory = null;

定义设置所有客户端套接字的工厂

public static synchronized void setSocketImplFactory(SocketImplFactory fac)throws IOException{if (factory != null) {throw new SocketException("factory already defined");}SecurityManager security = System.getSecurityManager();if (security != null) {security.checkSetFactory();}factory = fac;}

超详细的逐句介绍Java网络编程之Socket类函数源码讲解(全)相关推荐

  1. 浅谈Java网络编程之Socket (1)

    和大家一起分享的是Java网络编程之Socket.在Java中Socket可以理解为客户端或者服务器端的一个特殊的对象,这个对象有两个关键的方法,一个是getInputStream方法,另一个是get ...

  2. 浅谈Java网络编程之Socket (2)

    <浅谈Java网络编程之Socket (1)>中我们已经和大家说到客户端的网络编程,下面和大家分享的是服务器的实现代码. import java.net.*; import java.io ...

  3. 超详细的逐句介绍Java反射之Field类和InvocationTargetException类函数源码讲解(全)

    一.Field类和InvocationTargetException类 InvocationTargetException 是一个经过检查的异常,它包装了被调用的方法或构造函数抛出的异常.Field提 ...

  4. JAVA网络编程之Socket

    Socket网络编成是一种较为底层的网络数据传输,很多语言都支持. 本例是根据菜鸟教程中的Java网络编程而写. 详细内容参考请参考:http://www.runoob.com/java/java-n ...

  5. java网络编程之Socket编程

    概念 网络编程分为BIO(传统IO).NIO.AIO.Socket编程属于BIO这种传统IO. InetAddress java.net.InetAddress是JAVA中管理IP地址的类,常用 pu ...

  6. Java网络编程之Socket和ServerSocket详解

    Socket Socket是实现客户端套接字的类,套接字是两台计算机之间进行通信的端点. Socket的实际工作由SocketImpl类的实例执行 .通过更改用于创建套接字实现的套接字工厂,应用程序可 ...

  7. Java并发编程之AQS以及源码解析

    文章目录 概览 实现思路 实现原理 源自CLH锁 AQS数据模型 CAS操作 主要方法 自定义同步器的实现方法 AQS定义的模板方法 源码解读 等待状态释义 AQS获取锁的流程图 获取独占锁的实现 总 ...

  8. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. J ...

  9. Java网络编程之NIO编程(待补充)

    Java网络编程之NIO编程(待补充) 学习网站1:http://ifeve.com/java-nio-all/ 学习网站2:http://www.ibm.com/developerworks/cn/ ...

最新文章

  1. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程
  2. linux启动关闭脚本,Linux下自动启动关闭Oracle脚本
  3. 不用高温也能搓出一颗玻璃球?Science最新研究让低温注塑玻璃成为可能
  4. html 查询表单,如何让我的HTML表单查询适用于所有表单元素?
  5. MyBatisPlus插件扩展_PerformanceInterceptor性能分析插件的使用
  6. jQuery EasyUI API 中文文档 - 微调器(Spinner)
  7. ubuntu小企鹅输fcitx入法乱码问题
  8. mysql 索引_MySQL之索引
  9. linux 高性能日志,linux日志系统
  10. 使用spring最简单地读取properties文件中的内容
  11. android ndk问题,Android ndk helloWord 问题集锦
  12. vue部门结构图_Vue组织架构图组件
  13. 新浪微博api接口java_Java调用新浪微博API【转】
  14. 计算机关机后,电脑关机后自动重启怎么解决?
  15. 《浪潮之巅》内容整理
  16. 产品能力|书山有路-趣味算法(第二版)读书笔记part1
  17. 2021-06-25
  18. 计算机专业在职双证,计算机专业在职研究生可以获得在职研究生双证吗?
  19. java-final关键字修饰变量
  20. 运算符:is与==的区别

热门文章

  1. MATLAB 求解定积分和不定积分
  2. 第一周------继续
  3. egg框架结合egg-sequelize 建立数据库链接
  4. 手把手教你,5min中,实现OBS存储桶,搭建个人网盘(秒杀百度网盘VIP)
  5. PowerSI提取S参数(插损、回损、串扰分析)
  6. 7.3 Python 一维数据的格式化和处理
  7. Android TV Demo 工程,其中包含 TV 常用的自定义控件,飞框效果实现,外边框效果实现,UI 控件焦点自动处理,使 TV 开发更简单,更高效。
  8. Git--SSH登录
  9. paperpass论文查重
  10. 初学编程,到底选Java还是C++?