1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 超详细的逐句介绍Java网络编程之Socket类函数源码讲解(全)

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

时间:2019-03-15 05:14:55

相关推荐

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

一、Socket类

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

二、Socket类源码介绍

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

publicclass 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: .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();// .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(.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;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。