Java-WebSocket 项目的研究(二) 小试身手:客户端连接服务器并发送消息实例
的介绍我们大概了解到了整个项目的类结构,其中有一个重要的类:WebSocketClient,下面就让我们详细了解一下这个类
首先看一下我们之前的类图关于
WebSocketClient
的描述,可以看出:
1.继承自
WebSocketAdapter
2.依赖于类
WebSocketImpl
(实际上关于
WebSocket
核心代码都在类
WebSocketImpl
里)
3.实现了WebSocket接口(实际上通过类
WebSocketImpl
实现的)
很简单的,从字面意思我们就大概能猜到
WebSocketAdapter
是适配器类,架起了
WebSocketImpl
与
WebSocketClient
之间的桥梁,
WebSocketImpl
是web implementation的缩写,意思就是真正实现了websocket里主要的功能。
然后我们看一下
WebSocketClient
的几个主要方法:
首先是connect方法
-
/**
-
* 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();
- }
/**
* 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方法里去一探究竟
-
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() ); - }
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() );
}
下面我们对上面的代码进行详细研究:
-
socket =
new
Socket( proxy );
socket = new Socket( proxy );
这句显而易见,是创建了一个socket套接字。
-
socket.connect(
new
InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );
socket.connect( new InetSocketAddress( uri.getHost(), getPort() ), connectTimeout );
这句的意思是创建连接,参数就是服务器地址,端口号,超时时间。
- istream = socket.getInputStream();
istream = socket.getInputStream();
是接受服务器端的数据,关于接受的详细过程,我会在后期的博客中阐述,敬请期待。
- ostream = socket.getOutputStream();
ostream = socket.getOutputStream();
是发送数据用的。
其他的先不解释,我们继续之前的流程——connect之后就要发送信息,也就是调用send方法,send方法如下:
-
/**
-
* 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 );
- }
/**
* 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是啥东东呢,在类的声明处有这么一句话:
-
private
WebSocketImpl engine =
null
;
private WebSocketImpl engine = null;
说明了
WebSocketImpl类
实现了send的操作。