UDP中的connect方法 和TCP的connect方法详解

// SocketAddress 其实就是IP地址+端口号 , 而InetAddress 只有IP地址
connect(InetAddress address, int port) 
connect(SocketAddress addr)

UDP通过这样的方式,限定了单向的通信,但是注意的是,这里的限定只是仅限于一方,而并没有限制另外一方,另外一方依旧是可以向多个IP地址发送数据包的,因此这和TCP/IP 是极大的不同。TCP/IP的connect()是要有一个三次握手的过程的,而UDP的connect显然没有,它只是将IP地址和端口号进行了存储,对要进行通信的对象做了一个限制。 而且 TCP/IP的connect()只可以进行一次,但是UDP的connect()可以调用多次, 每次重新调用connect(SocketAddress ),就是将原来限制通信的对象修改为新的这个地址的对象, 或者调用disConnect() 方法,就会解除对通信对象的限制,这样这个socket就又可以多向的通信了。

当我们进行UDP通信的对象只有一个时,建议使用connect()方法,使用了这个方法之后有一个极大的好处: 当我们使用了connect(SocketAddress addr) 方法时,那么在socket对象里面就会将发送方的地址设置为此地址,那么发送的数据包对象就不用显式的标明 IP地址和 Port ,这样在调用send(packet)方法时,就不会对数据包再进行 IP地址和Port的安全检查,要发送的数据包少时优势体现不出来,但是当数据包多时,可以节省大量的时间。 send方法的源码:

public void send(DatagramPacket p) throws IOException  {
        InetAddress packetAddress = null;
        synchronized (p) {
            if (isClosed())
                throw new SocketException("Socket is closed");
            checkAddress (p.getAddress(), "send");
            // ST_NOT_CONNECTED 表示着当前没有要限制通信的对象 
            if (connectState == ST_NOT_CONNECTED) {
                // check the address is ok wiht the security manager on every send.
                SecurityManager security = System.getSecurityManager();

                // The reason you want to synchronize on datagram packet
                // is because you dont want an applet to change the address
                // while you are trying to send the packet for example
                // after the security check but before the send.
                // 进行IP 和 port 的安全检查
                if (security != null) {
                    if (p.getAddress().isMulticastAddress()) {
                        security.checkMulticast(p.getAddress());
                    } else {
                        security.checkConnect(p.getAddress().getHostAddress(),
                                              p.getPort());
                    }
                }
            } else {
                // were connected
                packetAddress = p.getAddress();
                if (packetAddress == null) {
                    p.setAddress(connectedAddress);
                    p.setPort(connectedPort);
                } else if ((!packetAddress.equals(connectedAddress)) ||
                           p.getPort() != connectedPort) {
                    throw new IllegalArgumentException("connected address " +
                                                       "and packet address" +
                                                       " differ");
                }
            }
            // Check whether the socket is bound
            if (!isBound())
                bind(new InetSocketAddress(0));
            // call the  method to send
            getImpl().send(p);
        }
    }

期间还看到了一个: bind(SocketAddress addr) 方法,是用来为创建的socket对象绑定到一个指定的 IP 地址和 Port号的,这个指定的是自身的IP和Port ,和上面的指定的要进行通信的对象的 IP 和 Port 不是一回事。

经验分享 程序员 微信小程序 职场和发展