`
king_tt
  • 浏览: 2124177 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

【网络编程】Socket基础

 
阅读更多

概述

Socket通常称为“套接字”。Socket字面上的中文意思为“插座”。一台服务器可能会提供很多服务,每种服务对应一个Socket(也可以这么说,每个Socket就是一个插座,客户若是需要哪种服务,就将插头插到相应的插座上面),而客户的“插头”也是一个Socket。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。Socket用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过套接字向网络发出请求或者应答网络请求。

Socket的基本操作包括:

  • 连接远程机器
  • 发送数据
  • 接收数据
  • 关闭连接
  • 绑定端口
  • 监听到达数据
  • 在绑定的端口上接受来自远程机器的连接

服务器要和客户端通信,两者都要实例化一个Socket。服务器和客户端的Socket是不一样的,客户端可以实现连接远程机器、发送数据、接收数据、关闭连接等,服务器还需要实现绑定端口,监听到达的数据,接受来自远程机器的连接。Android在包java.net里面提供了两个类:ServerSocket和Socket,前者用于实例化服务器的Socket,后者用于实例化客户端的Socket。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成客户端到服务器所需的会话。

接下来分析一些重要的Socket编程接口。首先是如何构造一个Socket,常用的构造客户端Socket的方法有以下几种。

  • Socket():创建一个新的未连接的Socket。
  • Socket(Proxy proxy):使用指定的代理类型创建一个新的未连接的Socket。
  • Socket(String dstName,int dstPort):使用指定的目标服务器的IP地址和目标服务器的端口号,创建一个新的Socket。
  • Socket(String dstName,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。
  • Socket(InetAddress dstAddress,int dstPort):使用指定的本地地址和本地端口,创建一个新的Socket。
  • Socket(InetAddress dstAddress,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的Socket。

其中,proxy为代理服务器地址,dstAddress为目标服务器IP地址,dstPort为目标服务器的端口号(因为服务器的每种服务都会绑定在一个端口上面),dstName为目标服务器的主机名。Socket构造函数代码举例如下所示:

// 第一个参数是目标服务器的IP地址,2012是目标服务器的端口号      
Socket client=new Socket("192.168.1.23", 2012);   
// 实例化一个Proxy,以该Proxy为参数,创建一个新的Socket 
Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("test.domain.org", 2130)));

注意 0~1023端口为系统保留,用户设定的端口号应该大于1023。

Socket类重要方法

/**
     * Gets an input stream to read data from this socket.
     *
     * @return the byte-oriented input stream.
     * @throws IOException
     *             if an error occurs while creating the input stream or the
     *             socket is in an invalid state.
     */
    public InputStream getInputStream() throws IOException {
        checkOpenAndCreate(false);
        if (isInputShutdown()) {
            throw new SocketException("Socket input is shutdown");
        }
        return impl.getInputStream();
    }
    /**
     * Gets an output stream to write data into this socket.
     *
     * @return the byte-oriented output stream.
     * @throws IOException
     *             if an error occurs while creating the output stream or the
     *             socket is in an invalid state.
     */
    public OutputStream getOutputStream() throws IOException {
        checkOpenAndCreate(false);
        if (isOutputShutdown()) {
            throw new SocketException("Socket output is shutdown");
        }
        return impl.getOutputStream();
    }
    /**
     * Closes the socket. It is not possible to reconnect or rebind to this
     * socket thereafter which means a new socket instance has to be created.
     *
     * @throws IOException
     *             if an error occurs while closing the socket.
     */
    public synchronized void close() throws IOException {
        isClosed = true;
        // RI compatibility: the RI returns the any address (but the original local port) after close.
        localAddress = Inet4Address.ANY;
        impl.close();
    }

上面是构造Socket客户端的几种常用的方法,构造服务器端的ServerSocket的方法有以下几种。

  • ServerSocket():构造一个新的未绑定的ServerSocket。
  • ServerSocket(int port):构造一个新的ServerSocket实例并绑定到指定端口。如果port参数为0,端口将由操作系统自动分配,此时进入队列的数目将被设置为50。
  • ServerSocket(int port,int backlog):构造一个新的ServerSocket实例并绑定到指定端口,并且指定进入队列的数目。如果port参数为0,端口将由操作系统自动分配。
  • ServerSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServerSocket实例并绑定到指定端口和指定的地址。如果localAddress参数为null,则可以使用任意地址,如果port参数为0,端口将由操作系统自动分配。

下面举例说明ServerSocket的构建方法,代码如下所示:

// 2012表示服务器要监听的端口号        
ServerSocket socketserver=new ServerSocket(2012);    

构造完ServerSocket之后,需要调用ServerSocket.accept()方法来等待客户端的请求(因为Socket都是绑定在端口上面的,所以知道是哪个客户端请求的)。accept()方法就会返回请求这个服务的客户端的Socket实例,然后通过返回的这个Socket实例的方法,操作传输过来的信息。当Socket对象操作完毕之后,使用close()方法将其关闭。

ServerSocket类重要方法

/**
     * Waits for an incoming request and blocks until the connection is opened.
     * This method returns a socket object representing the just opened
     * connection.
     *
     * @return the connection representing socket.
     * @throws IOException
     *             if an error occurs while accepting a new connection.
     */
    public Socket accept() throws IOException {
        checkClosedAndCreate(false);
        if (!isBound()) {
            throw new SocketException("Socket is not bound");
        }

        Socket aSocket = new Socket();
        try {
            implAccept(aSocket);
        } catch (SecurityException e) {
            aSocket.close();
            throw e;
        } catch (IOException e) {
            aSocket.close();
            throw e;
        }
        return aSocket;
    }
    /**
     * Closes this server socket and its implementation. Any attempt to connect
     * to this socket thereafter will fail.
     *
     * @throws IOException
     *             if an error occurs while closing this socket.
     */
    public void close() throws IOException {
        isClosed = true;
        impl.close();
    }

Socket一般有两种类型:TCP套接字和UDP套接字。

TCP和UDP在传输过程中的具体实现方法不同。两者都接收传输协议数据包并将其内容向前传送到应用层。TCP把消息分解成数据包(数据报,datagrams)并在接收端以正确的顺序把它们重新装配起来,TCP还处理对遗失数据包的重传请求,位于上层的应用层要处理的事情就少多了。UDP不提供装配和重传请求这些功能,它只是向前传送信息包。位于上层的应用层必须确保消息是完整的,并且是以正确的顺序装配的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics