java tcp底层源码分析

TCP服务端实现

     //定义服务器端socket并指定监听端口

    ServerSocket serverSocket = new ServerSocket(5937);

    //调用阻塞式方法来获取客户端连接的socket

    Socket socket = serverSocket.accept();

     //获取客户端socket的输入流

    InputStream inputStream =socket.getInputStream();

    //读取客户端socket的输入流的内容并输出

    byte[]buffer = new byte[512];

    inttemp;

    while((temp = inputStream.read(buffer)) != -1) {

         System.out.println(new String(buffer, 0, temp));

    }

TCP客户端实现

     //产生socket对象,制定服务器地址和服务器监听的端口号

    Socket socket = new Socket("127.0.0.1", 5937);

    //获取socket的输出流

    OutputStream outputStream =socket.getOutputStream();

    //将数据放入输出流中

    outputStream.write(msg.getBytes());

//定义服务器端socket并指定监听端口

ServerSocket serverSocket = new ServerSocket(5937);

//////////////////////////////////////////////////////////////////

java.net.ServerSocket.java96

/**

     * Constructs a new {@code ServerSocket}instance bound to the given {@code localAddress}

     * and {@code port}. The backlog is set to{@code backlog}.

     * If {@code localAddress == null}, the ANYaddress is used.

     * If {@code port == 0}, a port will beassigned by the OS.

     *

     * @throws IOException if an error occurs while creating the socket.

     */

public ServerSocket(int port, intbacklog, InetAddress localAddress) throwsIOException {

        checkListen(port);

        this.impl = factory != null ? factory.createSocketImpl()

                : new PlainServerSocketImpl();

        InetAddress addr = (localAddress == null) ? Inet4Address.ANY: localAddress;

        synchronized (this) {

            impl.create(true);

            try {

                impl.bind(addr,port);

                readBackBindState();

                impl.listen(backlog> 0 ? backlog : DEFAULT_BACKLOG);

            } catch (IOException e) {

                close();

                throw e;

            }

        }

    }

//////////////////////////////////////////////////////////////////

java:

FileDescriptor fd;

c++:

int fd;

int fd =jniGetFDFromFileDescriptor(env, javaFd);

定义:JNIHelp.cpp 320

FileDescriptor javaFd =jniCreateFileDescriptor(env, fd);

定义:JNIHelp.cpp 309

//////////////////////////////////////////////////////////////////

1.impl.create(true):

//////////////////////////////////////////////////////////////////

libcore.io.IoBridge.java606

public static FileDescriptor socket(boolean stream)

FileDescriptor fd;

fd = Libcore.os.socket(AF_INET6, stream ? SOCK_STREAM : SOCK_DGRAM, 0);

(stream : true)

获得远端fd

libcore_io_posix.cpp 1419

static jobject Posix_socket(JNIEnv* env,jobject, jint domain, jint type, jint protocol)

socket(domain, type,protocol)

//////////////////////////////////////////////////////////////////

libcore.io.IoBridge.java376

private static voidsetSocketOptionErrno(FileDescriptor fd, int option, Object value)

Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_REUSEADDR, booleanToInt((Boolean) value));

(value : Boolean.TRUE)

(booleanToInt((Boolean)value) : 1)

libcore_io_posix.cpp 1297

static void Posix_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jintlevel, jint option, jint value)

setsockopt(fd, level,option, &value, sizeof(value)))

//////////////////////////////////////////////////////////////////

2.impl.bind(addr, port):

libcore.io.IoBridge.java79

public static void bind(FileDescriptor fd,InetAddress address, int port)

Libcore.os.bind(fd, address, port);

libcore_io_posix.cpp 486

static void Posix_bind(JNIEnv* env, jobject, jobject javaFd, jobjectjavaAddress, jint port)

NET_FAIURE_RETRY(env, int, bind, javaFd, sa, sa_len);

宏定义:

bind(javaFd, sa, sa_len);

sa:

sockaddr_storage ss;

socklen_t sa_len;

inetAddressToSockaddr(env,javaAddress, port, ss, sa_len);

const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);

//////////////////////////////////////////////////////////////////

3.readBackBindState():

InetAddress localAddress

localAddress = IoBridge.getSocketLocalAddress(impl.fd);

获得本地IP端口

libcore.io.IoBridge.java627

public static InetAddress getSocketLocalAddress(FileDescriptor fd)

SocketAddress sa =Libcore.os.getsockname(fd);

libcore_io_posix.cpp 409

static jobject doGetSockName(JNIEnv* env,jobject javaFd, bool is_sockname)

sockaddr_storage ss;

sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);

socklen_t byteCount = sizeof(ss);

getsockname(fd, sa,&byteCount)

//////////////////////////////////////////////////////////////////

4.impl.listen(backlog > 0 ? backlog : DEFAULT_BACKLOG):

java.net.PlainSocketImpl.java271

protected void listen(int backlog)

Libcore.os.listen(fd,backlog);

libcore_io_posix.cpp 965

static void Posix_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog)

listen(fd, backlog);

backlog = DEFAULT_BACKLOG 50

//////////////////////////////////////////////////////////////////

//调用阻塞式方法来获取客户端连接的socket

Socket socket = serverSocket.accept();

//////////////////////////////////////////////////////////////////

/**

     * Waits for an incoming request and blocksuntil the connection is opened.

     * This method returns a socket objectrepresenting the just opened

     * connection.

     *

     * @return the connection representing socket.

     * @throws IOException

     *             if an error occurs while acceptinga new connection.

     */

    public Socket accept() throwsIOException {

        checkOpen();

        if(!isBound()) {

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

        }

        Socket aSocket = new Socket();

        try {

            implAccept(aSocket);

        } catch (IOException e) {

            aSocket.close();

            throw e;

        }

        return aSocket;

    }

1.isBound():

构造函数中readBackBindState() -> isBound = true;

2.implAccept(aSocket):

2.1.impl.accept(aSocket.impl):

(java.net.PlainSocketImpl.java80)

protected void accept(SocketImpl newImpl)

FileDescriptor clientFd =Libcore.os.accept(fd, peerAddress);

newImpl.fd.setInt$(clientFd.getInt$());

newImpl.address = peerAddress.getAddress();

newImpl.port = peerAddress.getPort();

获得对方远端IP端口

(libcore_io_posix.cpp460)

static jobject Posix_accept(JNIEnv* env,jobject, jobject javaFd, jobject javaInetSocketAddress)

jint clientFd =NET_FAIURE_RETRY(env, int, accept, javaFd, peer,peerLength);

宏定义:

accept(javaFd, peer,peerLength)

peer:

sockaddr_storage ss;

socklen_t sl = sizeof(ss);

memset(&ss, 0, sizeof(ss));

sockaddr* peer =(javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;

socklen_t* peerLength =(javaInetSocketAddress != NULL) ? &sl : 0;

//////////////////////////////////////////////////////////////////

2.2.aSocket.accepted():

InetAddress localAddress

localAddress = IoBridge.getSocketLocalAddress(impl.fd);

(获得对方本地IP端口)

同上1.3

//////////////////////////////////////////////////////////////////

//获取客户端socket的输入流

InputStream inputStream = socket.getInputStream();

//读取客户端socket的输入流的内容并输出

byte[] buffer= new byte[512];

int temp;

while ((temp = inputStream.read(buffer))!= -1) {

     System.out.println(new String(buffer, 0, temp));

}

//////////////////////////////////////////////////////////////////

@Override protected synchronized InputStream getInputStream() throws IOException {

        checkNotClosed();

        return new PlainSocketInputStream(this);

    }

    private static class PlainSocketInputStream extends InputStream {

        private final PlainSocketImpl socketImpl;

        public PlainSocketInputStream(PlainSocketImpl socketImpl) {

            this.socketImpl = socketImpl;

        }

        @Override public int available() throws IOException {

            return socketImpl.available();

        }

        @Override public void close() throws IOException {

            socketImpl.close();

        }

        @Override public int read() throws IOException {

            return Streams.readSingleByte(this);

        }

        @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {

            return socketImpl.read(buffer, byteOffset,byteCount);

        }

    }

/**

     * For PlainSocketInputStream.

     */

    private int read(byte[] buffer, int offset, int byteCount) throwsIOException {

        if(byteCount == 0) {

            return 0;

        }

        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);

        if(shutdownInput) {

            return -1;

        }

        int readCount = IoBridge.recvfrom(true, fd, buffer, offset, byteCount, 0, null, false);

        // Return of zero bytes for a blocking socket means atimeout occurred

        if(readCount == 0) {

            throw new SocketTimeoutException();

        }

        // Return of -1 indicates the peer was closed

        if(readCount == -1) {

            shutdownInput = true;

        }

        return readCount;

    }

(libcore.io.IoBridge.java549)

public static int recvfrom(boolean isRead, FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, DatagramPacket packet, boolean isConnected)

result = Libcore.os.recvfrom(fd, bytes, byteOffset, byteCount, flags,srcAddress);

(libcore_io_posix.cpp1185)

static jint Posix_recvfromBytes(JNIEnv*env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jintbyteCount, jint flags, jobject javaInetSocketAddress)

NET_FAIURE_RETRY(env,ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);

宏定义:

recvfrom(javaFd,bytes.get() + byteOffset, byteCount, flags, from, fromLength);

bytes : ScopedBytesRWbytes(env, javaBytes);

byteOffset : 0

flags : 0

from : BULL

fromLength : 0

问题:

为什么java tcp接收底层代码是recvfrom()而不是read()?

猜你喜欢

转载自blog.csdn.net/xuqiqiang1993/article/details/66974923