Java-WebSocket 项目的研究(三) WebSocketClient 类 详解

  • Post author:
  • Post category:java


通过之前两篇文章



Java-WebSocket 项目的研究(一) Java-WebSocket类图描述





Java-WebSocket 项目的研究(二) 小试身手:客户端连接服务器并发送消息实例



的介绍我们大概了解到了整个项目的类结构,其中有一个重要的类:WebSocketClient,下面就让我们详细了解一下这个类

首先看一下我们之前的类图关于

WebSocketClient

的描述,可以看出:

1.继承自

WebSocketAdapter

2.依赖于类

WebSocketImpl

(实际上关于

WebSocket

核心代码都在类

WebSocketImpl

里)

3.实现了WebSocket接口(实际上通过类

WebSocketImpl

实现的)

很简单的,从字面意思我们就大概能猜到

WebSocketAdapter

是适配器类,架起了

WebSocketImpl



WebSocketClient

之间的桥梁,

WebSocketImpl

是web implementation的缩写,意思就是真正实现了websocket里主要的功能。

然后我们看一下

WebSocketClient

的几个主要方法:

首先是connect方法


  1. /**

  2. * Initiates the websocket connection. This method does not block.

  3. */

  4. public


    void

    connect() {

  5. if

    ( writeThread !=

    null

    )

  6. throw


    new

    IllegalStateException(

    “WebSocketClient objects are not reuseable”

    );
  7. writeThread =

    new

    Thread(

    this

    );
  8. writeThread.start();
  9. }
/**
	 * Initiates the websocket connection. This method does not block.
	 */
	public void connect() {
		if( writeThread != null )
			throw new IllegalStateException( "WebSocketClient objects are not reuseable" );
		writeThread = new Thread( this );
		writeThread.start();
	}

我们可以发现:

他其实是起了一个线程,由于

WebSocketClient

类实现了Runnable接口,因此他会自动去调用run方法,然后我们进一步到run方法里去一探究竟


  1. public


    void

    run() {

  2. try

    {

  3. if

    ( socket ==

    null

    ) {
  4. socket =

    new

    Socket( proxy );
  5. }

    else


    if

    ( socket.isClosed() ) {

  6. throw


    new

    IOException();
  7. }
  8. System.out.println(

    “—->  ”

    +uri.toString()+

    ”   port: ”

    +getPort() );

  9. if

    ( !socket.isBound() )
  10. socket.connect(

    new

    InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );
  11. istream = socket.getInputStream();
  12. ostream = socket.getOutputStream();
  13. sendHandshake();
  14. }

    catch

    (

    /*IOException | SecurityException | UnresolvedAddressException | InvalidHandshakeException | ClosedByInterruptException | SocketTimeoutException */

    Exception e ) {
  15. onWebsocketError( engine, e );
  16. engine.closeConnection( CloseFrame.NEVER_CONNECTED, e.getMessage() );

  17. return

    ;
  18. }
  19. writeThread =

    new

    Thread(

    new

    WebsocketWriteThread() );
  20. writeThread.start();

  21. byte

    [] rawbuffer =

    new


    byte

    [ WebSocketImpl.RCVBUF ];

  22. int

    readBytes;

  23. try

    {

  24. while

    ( !isClosed() && ( readBytes = istream.read( rawbuffer ) ) != –

    1

    ) {
  25. engine.decode( ByteBuffer.wrap( rawbuffer,

    0

    , readBytes ) );
  26. }
  27. engine.eot();
  28. }

    catch

    ( IOException e ) {
  29. engine.eot();
  30. }

    catch

    ( RuntimeException e ) {

  31. // this catch case covers internal errors only and indicates a bug in this websocket implementation
  32. onError( e );
  33. engine.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
  34. }

  35. assert

    ( socket.isClosed() );
  36. }
public void run() {
		try {
			if( socket == null ) {
				socket = new Socket( proxy );
			} else if( socket.isClosed() ) {
				throw new IOException();
			}
			System.out.println("---->  "+uri.toString()+"   port: "+getPort() );
			if( !socket.isBound() )
				socket.connect( new InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );
			istream = socket.getInputStream();
			ostream = socket.getOutputStream();

			sendHandshake();
		} catch ( /*IOException | SecurityException | UnresolvedAddressException | InvalidHandshakeException | ClosedByInterruptException | SocketTimeoutException */Exception e ) {
			onWebsocketError( engine, e );
			engine.closeConnection( CloseFrame.NEVER_CONNECTED, e.getMessage() );
			return;
		}

		writeThread = new Thread( new WebsocketWriteThread() );
		writeThread.start();

		byte[] rawbuffer = new byte[ WebSocketImpl.RCVBUF ];
		int readBytes;

		try {
			while ( !isClosed() && ( readBytes = istream.read( rawbuffer ) ) != -1 ) {
				engine.decode( ByteBuffer.wrap( rawbuffer, 0, readBytes ) );
			}
			engine.eot();
		} catch ( IOException e ) {
			engine.eot();
		} catch ( RuntimeException e ) {
			// this catch case covers internal errors only and indicates a bug in this websocket implementation
			onError( e );
			engine.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
		}
		assert ( socket.isClosed() );
	}

下面我们对上面的代码进行详细研究:

  1. socket =

    new

    Socket( proxy );
				socket = new Socket( proxy );

这句显而易见,是创建了一个socket套接字。

  1. socket.connect(

    new

    InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );
				socket.connect( new InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );

这句的意思是创建连接,参数就是服务器地址,端口号,超时时间。

  1. istream = socket.getInputStream();
			istream = socket.getInputStream();

是接受服务器端的数据,关于接受的详细过程,我会在后期的博客中阐述,敬请期待。

  1. ostream = socket.getOutputStream();
			ostream = socket.getOutputStream();

是发送数据用的。

其他的先不解释,我们继续之前的流程——connect之后就要发送信息,也就是调用send方法,send方法如下:


  1. /**

  2. * Sends <var>text</var> to the connected websocket server.

  3. *

  4. * @param text

  5. *            The string which will be transmitted.

  6. */

  7. public


    void

    send( String text )

    throws

    NotYetConnectedException {
  8. engine.send( text );
  9. }
/**
	 * Sends <var>text</var> to the connected websocket server.
	 * 
	 * @param text
	 *            The string which will be transmitted.
	 */
	public void send( String text ) throws NotYetConnectedException {
		engine.send( text );
	}

它调用了engine的send方法,那么engine是啥东东呢,在类的声明处有这么一句话:


  1. private

    WebSocketImpl engine =

    null

    ;
	private WebSocketImpl engine = null;

说明了

WebSocketImpl类

实现了send的操作。

转自:

http://blog.csdn.net/zjh171/article/details/24800493