日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

api有哪些 javasocket_socket及socket java api

發布時間:2023/12/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 api有哪些 javasocket_socket及socket java api 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

wiki上對于soket的定義

1.起源:

起源于https://tools.ietf.org/html/rfc147

2.套接字主要是在Internet模型的傳輸層中使用的概念。路由器和交換機等網絡設備一般不需要傳輸層的實現,因為它們一般在鏈路層(交換機)或互聯網層(路由器)上運行。

3.類型

數據報套接字,也稱為無連接套接字,使用用戶數據報協議(UDP)。

流套接字,也稱為面向連接的套接字,使用傳輸控制協議(TCP),流控制傳輸協議(SCTP)或數據報擁塞控制協議(DCCP)。

原始套接字(或原始IP套接字),通常在路由器和其他網絡設備中可用。這里繞過傳輸層,并且應用程序可以訪問包頭,并且地址中沒有端口號,只有IP地址。

廣義:socket有兩種場景。

本篇重點:網絡套接字以及Java關于socket api

首先回顧7層網絡模型

10dfa9ec8a1363270baa4fcb9b8fa0ec09fac787.jpg

由上面socket類型所知,socket主要是傳輸層的概念,主要也就是udp,和tcp兩種情況。(另外一種暫不討論)

先看下api

實例代碼:

try {

new Socket("127.0.0.1",80);

} catch (UnknownHostException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

1.常用構造器

public Socket(InetAddress address, int port) throws IOException {

this(address != null ? new InetSocketAddress(address, port) : null,

(SocketAddress) null, true);

}

private Socket(SocketAddress address, SocketAddress localAddr,

boolean stream) throws IOException {

setImpl();

// backward compatibility

if (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;

}

}

1.以上構造器創建了一個IP Socket Address ,基于ip協議的SocketAddress(IP address + port number)

public InetSocketAddress(InetAddress addr, int port) {

holder = new InetSocketAddressHolder(

null,

addr == null ? InetAddress.anyLocalAddress() : addr,

checkPort(port));

}

2.創建SocksSocketImpl

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);

}

createImpl 即SocksSocketImpl::createImpl

SocksSocketImpl是AbstractPlainSocketImpl的子類,最終看AbstractPlainSocketImpl的createImpl。由代碼可知,最終的socket創建是由AbstractPlainSocketImpl創建的。如果是tcp,create(boolean stream)參數為true;如果是udp,參數為false。

/**

* Creates a socket with a boolean that specifies whether this

* is a stream socket (true) or an unconnected UDP socket (false).

*/

protected synchronized void create(boolean stream) throws IOException {

this.stream = stream;

if (!stream) {

ResourceManager.beforeUdpCreate();

// only create the fd after we know we will be able to create the socket

fd = new FileDescriptor();

try {

socketCreate(false);

} catch (IOException ioe) {

ResourceManager.afterUdpClose();

fd = null;

throw ioe;

}

} else {

fd = new FileDescriptor();

socketCreate(true);//子類PlainSocketImpl調用native void socketCreate(boolean isServer) throws IOException;

}

if (socket != null)

socket.setCreated();

//這里的socket,即開始new 的socket(“127.0.0.1”,80)對象

if (serverSocket != null)

serverSocket.setCreated();

}

3.在接著回到開始創建socket的代碼:創建完socket,接著校驗地址是否是IP4或ip6格式,校驗端口是否有權限(如果端口不允許訪問,會拋異常SecurityException),接著就開始bind遠程地址,并開始connect。

if (localAddr != null)

bind(localAddr);

connect(address);

bind最終調用的是SocksSocketImpl,即PlainSocketImpl的本地方法

getImpl().bind (addr, port);

protected synchronized void bind(InetAddress address, int lport)

throws IOException

{

synchronized (fdLock) {

if (!closePending && (socket == null || !socket.isBound())) {

NetHooks.beforeTcpBind(fd, address, lport);

}

}

socketBind(address, lport);//PlainSocketImpl 的native void socketBind(InetAddress address, int port)

throws IOException;

if (socket != null)

socket.setBound();

if (serverSocket != null)

serverSocket.setBound();

}

接著看connect

public void connect(SocketAddress endpoint) throws IOException {

connect(endpoint, 0);

}

//關鍵代碼

//再次校驗ip地址等

.....

else if (timeout == 0) {

if (epoint.isUnresolved())

impl.connect(addr.getHostName(), port);

else

impl.connect(addr, port);

} else

throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");

connected = true;

bound = true;

上面連接的流程,默認timeout為0,直接連接,不支持超時。

改過程為阻塞的。( The connection will then block until established or an error occurs.)

protected void connect(String host, int port)

throws UnknownHostException, IOException

{

boolean connected = false;

try {

InetAddress address = InetAddress.getByName(host);

this.port = port;

this.address = address;

connectToAddress(address, port, timeout);

connected = true;

} finally {

if (!connected) {

try {

close();

} catch (IOException ioe) {

/* Do nothing. If connect threw an exception then

it will be passed up the call stack */

}

}

}

}

最終也是AbstractPlainSocketImpl調用子類PlainSocketImpl的本地方法socketConnect,來連接。

4.服務端socket創建, ServerSocket和Socket是完全相干的兩個類。

但是他們的初始化,共同點:如果指定端口,都會在初始化的時候嘗試bind本地端口,并判斷該端口是否有權限。區別:Socket如果初始化指定了(IP,port)除了bind外,會多一步connect的操作。

new ServerSocket(80);

public

class ServerSocket implements java.io.Closeable

public ServerSocket(int port) throws IOException {

this(port, 50, null);

}

ServerSocket(port)默認隊列大小50.當超過50的連接會被拒絕。

getImpl().bind(epoint.getAddress(), epoint.getPort());

getImpl().listen(backlog);

bound = true;

結下來看,accept():阻塞的,除非接收到一個連接。

步驟:創建一個unconnected Socket,并調用implAccept(s)

* Listens for a connection to be made to this socket and accepts

* it. The method blocks until a connection is made.

*

*

A new Socket {@code s} is created and, if there

* is a security manager,

* the security manager's {@code checkAccept} method is called

* with {@code s.getInetAddress().getHostAddress()} and

* {@code s.getPort()}

* as its arguments to ensure the operation is allowed.

* This could result in a SecurityException.

*

* @exception IOException if an I/O error occurs when waiting for a

* connection.

* @exception SecurityException if a security manager exists and its

* {@code checkAccept} method doesn't allow the operation.

* @exception SocketTimeoutException if a timeout was previously set with setSoTimeout and

* the timeout has been reached.

* @exception java.nio.channels.IllegalBlockingModeException

* if this socket has an associated channel, the channel is in

* non-blocking mode, and there is no connection ready to be

* accepted

public Socket accept() throws IOException {

if (isClosed())

throw new SocketException("Socket is closed");

if (!isBound())

throw new SocketException("Socket is not bound yet");

Socket s = new Socket((SocketImpl) null);

implAccept(s);

return s;

}

接下來,和客戶端socket一樣,默認新建SocksSocketImpl對象,并添加新的InetAddress對象

protected final void implAccept(Socket s) throws IOException {

SocketImpl si = null;

try {

if (s.impl == null)

s.setImpl();

else {

s.impl.reset();

}

si = s.impl;

s.impl = null;

si.address = new InetAddress();

si.fd = new FileDescriptor();

getImpl().accept(si);

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkAccept(si.getInetAddress().getHostAddress(),

si.getPort());

}

} catch (IOException e) {

if (si != null)

si.reset();

s.impl = si;

throw e;

} catch (SecurityException e) {

if (si != null)

si.reset();

s.impl = si;

throw e;

}

s.impl = si;

s.postAccept();

}

/**

* Constructor for the Socket.accept() method.

* This creates an empty InetAddress, which is filled in by

* the accept() method. This InetAddress, however, is not

* put in the address cache, since it is not created by name.

*/

InetAddress() {

holder = new InetAddressHolder();

}

調用新建SocksSocketImpl的accept,即AbstractPlainSocketImpl的accept,如下:

/**

* Accepts connections.

* @param s the connection

*/

protected void accept(SocketImpl s) throws IOException {

acquireFD();

try {

socketAccept(s);//子類PlainSocketImpl的本地方法 native void socketAccept(SocketImpl s) throws IOException;

} finally {

releaseFD();//釋放fd

}

}

/*

* "Release" the FileDescriptor for this impl.

*

* If the use count goes to -1 then the socket is closed.

*/

void releaseFD() {

synchronized (fdLock) {

fdUseCount--;

if (fdUseCount == -1) {

if (fd != null) {

try {

socketClose();

} catch (IOException e) {

} finally {

fd = null;

}

}

}

}

}

題外話:

socket體系這里面涉及到了工廠的設計模式。方便內容的擴展。如果設置了factory,就按照自己設置的factory去實現

SocketImpl。代碼如下:

/**

* Sets impl to the system-default type of SocketImpl.

* @since 1.4

*/

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);

}

public

interface SocketImplFactory {

/**

* Creates a new {@code SocketImpl} instance.

*

* @return a new instance of {@code SocketImpl}.

* @see java.net.SocketImpl

*/

SocketImpl createSocketImpl();

}

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;

}

總結

以上是生活随笔為你收集整理的api有哪些 javasocket_socket及socket java api的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。