SOCKET
的封裝
C++
通用框架的設計
作者:
naven
1??????????
SOCKET
封裝介紹
Socket
通訊程序估計現(xiàn)在大多數(shù)應用系統(tǒng)都會涉及到,因為現(xiàn)在的世界是一個由
Internet
網(wǎng)絡連接的世界,任何個人電腦或服務都可能會有數(shù)據(jù)交換,通過
TCP/UDP
這樣的
Socket
通訊協(xié)議進行聯(lián)系。開發(fā)這樣的通訊程序會是很普遍也很類似,每種操作系統(tǒng)都實現(xiàn)了
Socket
通訊庫并提供很相似的
API
,通訊步驟都遵循
RFC
規(guī)范。但是有些
API
的具體接口卻稍有不同,比如
Socket IO API
在
win32
系統(tǒng)和
Unix
系統(tǒng)就不一樣,
Win32
用
recv/send
而
Unix
使用標準統(tǒng)一的
read/write
,而且
socket
句柄在不同操作系統(tǒng)處理也不一樣,等等這些都造成編寫跨平臺的
Socket
應用不太容易。另外編寫服務器和客戶端的處理步驟也很繁瑣,
IP
地址和域名的轉換也很麻煩,所以實現(xiàn)一個標準統(tǒng)一使用更簡潔的
API
非常有用。本
C++
框架基本參考
Java
的
Socket
相關類實現(xiàn)了類似封裝,除了
ServerSocket
實現(xiàn)稍有不同,其他原理和方法基本類似。用它編寫網(wǎng)絡應用基本不用考慮底層的協(xié)議處理,使用非常容易,代碼也更簡潔易讀。
?
主要有如下一些類
?
class Socket ?????????????????????? ???????????????????????????
代表一個
TCP
連接的
Socket
對象
???????? class DatagramSocket???????????????????????????????????
代表一個
UDP
連接的
Socket
對象(暫未實現(xiàn))
???????? class MulticastSocket???????????????????????????????????
一個
DatagramSocket
的子類用于多播(暫未實現(xiàn))
class SocketAcceptor???????????????????????????????????
一個
TCP
服務端的接收器
class SocketConnector?????????????????????????????????
一個
TCP
客戶端的連接器
???????? class SocketInputStream??????????????????????????????
一個
Socket
連接的輸入流
???????? class SocketOutputStream???????????????????????????
一個
Socket
連接的輸出流
???????? class SocketReader???????????????????????????????????????
一個
Socket
連接的讀操作器
???????? class SocketWriter?????????????????????????????????????????
一個
Socket
連接的寫操作器
?
Socket
的意思是在網(wǎng)絡的機器之間建立一個通信線路。通過
TCP Sockets
發(fā)送或接收的操作時通過
InputStream
和
OutputStream
流處理的,
Socket
類的
getInputStream
和
getOutputStream
可以取得該
Socket
連接的輸入
/
輸出流對象。
SocketAcceptor
是用于服務器端的接收器,它處于接收的狀態(tài)時會阻塞,直到接收到客戶端的連接請求,這時就會創(chuàng)建一個
Socket
對象代表該服務器到此客戶端的連接。而對應的
SocketConnector
是用于客戶端的連接器,它向服務端發(fā)出連接請求,如果服務器允許連接,則也同時建立一個
Socket
對象表示它到服務器端的連接,這時就可以獲取輸入
/
輸出流對象進行
Socket
通訊了。
2??????????
Hello World!
下面的程序示例如何用上面的類進行
Scoket
通訊:
這是服務端的實現(xiàn)
void
?servertest()?

{
????
//
?定義一個接收器綁定?8000?端口
????SocketAcceptor?sa(
8000
);?
????
while
(
1
)?

{
???????
//
?阻塞等待連接請求
????????Socket?sk?
=
?sa.accept();?
????????
//
?獲取此連接的讀操作器和寫操作器
????????Reader?
&
rd?
=
?sk.getReader();?
????????Writer?
&
wr?
=
?sk.getWriter();?
????????String?s;?
????????
//
?從客戶端讀取?10?個字節(jié)
????????rd.read(s,?
10
);?
????????
//
?向客戶端寫信息
????????wr.write(“read?ok”);?
????????
//
?關閉連接
????????sk.close();?
}
}
這是客戶端的實現(xiàn)
void
?clienttest()

{
????
//
?定義一個連接器
SocketConnector?sc;?
//
?連接指定的服務器地址及端口,?返回一個Socket對象
Socket?sk?
=
?sc.connect(“l(fā)ocalhost”,?
8000
);?
//
?如果已成功連上
????
if
(?sk.isConnected()?)?

{
????
//
?獲取此連接的讀操作器和寫操作器
????????Reader
&
?reader?
=
?sk.getReader();?
????????Writer
&
?writer?
=
?sk.getWriter();?
????????
//
?可以在讀操作器上建立一個帶緩沖的讀操作器
????????BufferedReader?rd(reader);
????????
//
?向服務器發(fā)送信息
????????writer.write(“hello?server”);
????????
//
?接收信息,?帶緩沖的讀操作器可以讀取一行
????????rd.readLine(s);
????????
//
?關閉連接
????????sk.close();
????}
}
1??????????
Socket
類
此類定義一個表示
Socket
連接的類,一個
Socket
是一個為在兩臺機器間通信的端點。一個
Socket
類的真實行為是通過一個
SocketImpl
類的詩體執(zhí)行的。一個應用程序可以通過改變
Socket Factory
來創(chuàng)建
Socket
的具體實現(xiàn),以適應本地的局域網(wǎng)防火墻。
Socket
類成員和主要接口定義如下:
?
class
?Socket?:?
public
?AbstractFile?

{
protected
:?

????
/**/
/*
*
?????*?The?implementation?of?this?Socket.
?????
*/
????SocketImplAutoPtr?_impl;?


????
/**/
/*
*
?????*?Various?states?of?this?socket.
?????
*/
????BOOL?_connected;?
????BOOL?_closed;?
????BOOL?_shutIn;?
BOOL?_shutOut;

public
:?

????
/**/
/*
*
?????*?Creates?an?unconnected?socket,?with?the
?????*?system-default?type?of?SocketImpl.
?????
*/
Socket();


????
/**/
/*
*
?????*?Returns?an?input?stream?for?this?socket.
?????*
?????*?@return?????an?input?stream?for?reading?bytes?from?this?socket.
?????
*/
????InputStream
&
?getInputStream();


????
/**/
/*
*
?????*?Gets?an?Reader?for?this?socket.
?????
*/
????Reader
&
?getReader();


????
/**/
/*
*
?????*?Returns?an?output?stream?for?this?socket.
?????*
?????*?@return?????an?output?stream?for?writing?bytes?to?this?socket.
?????
*/
????OutputStream
&
?getOutputStream();


????
/**/
/*
*
?????*?Gets?an?Writer?for?this?socket.
?????
*/
????Writer
&
?getWriter();?


????
/**/
/*
*
?????*?Enable/disable?the?option?specified?by?<I>optID</I>.??If?the?option
?????*?is?to?be?enabled,?and?it?takes?an?option-specific?"optval",??this?is
?????*?passed?in?<I>value</I>.??The?actual?type?of?value?is?option-specific,
?????*?and?it?is?an?error?to?pass?something?that?isn't?of?the?expected?type:
?????*?<BR>
?????*
?????*?@param?optID?identifies?the?option
?????*?@param?level?[in]?Level?at?which?the?option?is?defined;?the?supported?levels?
?????*??????????????include?SOL_SOCKET?and?IPPROTO_TCP.?
?????*?@param?optval?[in]?Pointer?to?the?buffer?in?which?the?value?for?the?requested?
?????*??????????????option?is?to?be?returned.
?????*?@param?optlen?[in]?Pointer?to?the?size?of?the?optval?buffer,?in?bytes.?
?????*?@return?0?If?no?error?occurs,?Otherwise,?a?value?of?SOCKET_ERROR(-1)?is?returned,?
?????*??????????and?a?specific?error?code?can?be?retrieved?by?socketerrno.
?????*?@see?#getOption(int)
?????
*/
????
int
?setOption(
int
?optID,?
int
?level,?
const
?
void
?
*
optval,?
int
?optlen);


????
/**/
/*
*
?????*?Fetch?the?value?of?an?option.
?????*?Binary?options?will?return?java.lang.Boolean(true)
?????*?if?enabled,?java.lang.Boolean(false)?if?disabled,?e.g.:
?????*?<BR>
?????*
?????*?@param?optID?an?<code>int</code>?identifying?the?option?to?fetch
?????*?@param?level?[in]?Level?at?which?the?option?is?defined;?the?supported?levels?
?????*??????????????include?SOL_SOCKET?and?IPPROTO_TCP.?
?????*?@param?optval?[out]?Pointer?to?the?buffer?in?which?the?value?for?the?requested?
?????*??????????????option?is?to?be?returned.
?????*?@param?optlen?[in,?out]?Pointer?to?the?size?of?the?optval?buffer,?in?bytes.?
?????*?@return?0?If?no?error?occurs,?Otherwise,?a?value?of?SOCKET_ERROR(-1)?is?returned,?
?????*??????????and?a?specific?error?code?can?be?retrieved?by?socketerrno.
?????*?@see?#setOption(int,?java.lang.Object)
?????
*/
????
int
?getOption(
int
?optID,?
int
?level,?
void
?
*
optval,?
int
?
*
optlen);


????
/**/
/*
*
?????*?Closes?this?socket.
?????*?<p>
?????*?Any?thread?currently?blocked?in?an?I/O?operation?upon?this?socket
?????*?will?throw?a?{@link?SocketException}.
?????*?<p>
?????*?Once?a?socket?has?been?closed,?it?is?not?available?for?further?networking
?????*?use?(i.e.?can't?be?reconnected?or?rebound).?A?new?socket?needs?to?be
?????*?created.
?????*
?????*?<p>?If?this?socket?has?an?associated?channel?then?the?channel?is?closed
?????*?as?well.
?????*
?????
*/
????
void
?close();

}
;
?
1?????????? SocketAcceptor類
此類實現(xiàn)一個用于服務器端接收連接的類。一個SocketAcceptor對象等待來自網(wǎng)絡的連接請求,它執(zhí)行一些基于請求的操作,并且可能返回一些信息給請求者。連接成功后SocketAcceptor會生成一個Socket對象用于網(wǎng)絡通訊。
SocketAcceptor類成員和主要接口定義如下:
?
class?SocketAcceptor


{
protected:?

????/**//**
?????*?The?factory?for?all?server?sockets.
?????*/
????static?SocketImplFactoryAutoPtr?_factory;?


????/**//**
?????*?The?implementation?of?this?Socket.
?????*/
????SocketImplAutoPtr?_impl;?


????/**//**
?????*?Various?states?of?this?socket.
?????*/
????BOOL?_bound;?
????BOOL?_created;?
????BOOL?_closed;?
????BOOL?_stream;?

public:?

????/**//**
?????*?Creates?a?socket?acceptor?with?default?stream?type.
?????*?<p>
?????*/
????SocketAcceptor();?


????/**//**
?????*?Creates?a?socket?acceptor?with?specified?stream?type,?
?????*?bound?to?the?specified?port?and?host.?A?port?of?
?????*?<code>0</code>?creates?a?socket?on?any?free?port.?
?????*?<p>
?????*?The?maximum?queue?length?for?incoming?connection?indications?(a?
?????*?request?to?connect)?is?set?to?<code>50</code>.?If?a?connection?
?????*?indication?arrives?when?the?queue?is?full,?the?connection?is?refused.
?????*?<p>
?????*?If?the?application?has?specified?a?server?socket?factory,?that?
?????*?factory's?<code>createSocketImpl</code>?method?is?called?to?create?
?????*?the?actual?socket?implementation.?Otherwise?a?"plain"?socket?is?created.
?????*?<p>
?????*
?????*?@param??????host?the?host?address?the?server?will?bind?to
?????*?@param??????port??the?port?number,?or?<code>0</code>?to?use?any
?????*???????????????????free?port.
?????*?@param??????stream????if?<code>true</code>,?create?a?stream?socket;
?????*???????????????????????otherwise,?create?a?datagram?socket.
?????*?@param??????backlog?the?listen?backlog
?????*/
SocketAcceptor(const?String?&host,?int?port,?BOOL?stream?=?TRUE);


????/**//**
?????*?Binds?the?<code>ServerSocket</code>?to?a?local?address
?????*?(IP?address?and?port?number).
?????*?<P>
?????*?The?<code>backlog</code>?argument?must?be?a?positive
?????*?value?greater?than?0.?If?the?value?passed?if?equal?or?less
?????*?than?0,?then?the?default?value?will?be?assumed.
?????*?@param?port?the?local?TCP?port
?????*?@param?backlog?the?listen?backlog
?????*?@return?0?If?no?error?occurs,?Otherwise,?a?value?of?
?????*??????????SOCKET_ERROR(-1)?is?returned
?????*/
????int?bind(int?port,?int?backlog?=?LISTENQ);


????/**//**
?????*?Listens?for?a?connection?to?be?made?to?this?socket?and?accepts?
?????*?it.?The?method?blocks?until?a?connection?is?made.?
?????*
?????*?<p>A?new?Socket?<code>s</code>?is?created?and,?if?there?
?????*?is?a?security?manager,?
?????*?the?security?manager's?<code>checkAccept</code>?method?is?called
?????*?with?<code>s.getInetAddress().getHostAddress()</code>?and
?????*?<code>s.getPort()</code>
?????*
?????*?@param?timeout??timeout?to?accept?in?ms.?
?????*?@return?the?new?Socket
?????*/
????Socket?accept(int?timeout);?


????/**//**
?????*?Closes?this?socket?acceptor.
?????*?<p>
?????*?Any?thread?currently?blocked?in?an?I/O?operation?upon?this?socket
?????*?will?throw?a?{@link?SocketException}.
?????*?<p>
?????*?Once?a?socket?has?been?closed,?it?is?not?available?for?further?networking
?????*?use?(i.e.?can't?be?reconnected?or?rebound).?A?new?socket?needs?to?be
?????*?created.
?????*
?????*?<p>?If?this?socket?has?an?associated?channel?then?the?channel?is?closed
?????*?as?well.
?????*
?????*/
????void?close();

};

1?????????? SocketConnector類
此類實現(xiàn)一個用于客戶器端連接服務的類。一個SocketConnector對象可以向指定的服務地址和端口發(fā)出的連接請求,它執(zhí)行一些基于請求的操作,并且可能返回一些信息。連接成功后SocketConnector會生成一個Socket對象用于網(wǎng)絡通訊。
SocketConnector類成員和主要接口定義如下:
class?SocketConnector


{
protected:?

????/**//**
?????*?The?factory?for?all?server?sockets.
?????*/
????static?SocketImplFactoryAutoPtr?_factory;?


????/**//**
?????*?The?implementation?of?this?Socket.
?????*/
????SocketImplAutoPtr?_impl;?


????/**//**
?????*?Various?states?of?this?socket.
?????*/
????BOOL?_bound;?
????BOOL?_created;?
????BOOL?_closed;?
????BOOL?_stream;;?

public:?

????/**//**
?????*?Creates?a?socket?connector?with?specified?stream?type.
?????*?default?is?Creates?a?stream?socket?connector.?
?????*?<p>
?????*
?????*?@param??????stream????if?<code>true</code>,?create?a?stream?socket;
?????*???????????????????????otherwise,?create?a?datagram?socket.
?????*/
????SocketConnector(BOOL?stream?=?TRUE);


????/**//**
?????*?Creates?a?socket?and?connects?it?to?the?specified?port?on
?????*?the?specified?host.
?????*?@param?host?the?specified?host
?????*?@param?port?the?specified?port
?????*?@param?timeout?the?timeout?value?in?milliseconds,?or?zero?for?no?timeout.
?????*??????????-1?will?use?default?timeout.
?????*?@return?the?new?Socket
?????*/
Socket?connect(const?String?&host,?int?port,?int?timeout?=?-1);


????/**//**
?????*?Closes?this?socket?connector.
?????*?<p>
?????*?Any?thread?currently?blocked?in?an?I/O?operation?upon?this?socket
?????*?will?throw?a?{@link?SocketException}.
?????*?<p>
?????*?Once?a?socket?has?been?closed,?it?is?not?available?for?further?networking
?????*?use?(i.e.?can't?be?reconnected?or?rebound).?A?new?socket?needs?to?be
?????*?created.
?????*
?????*?<p>?If?this?socket?has?an?associated?channel?then?the?channel?is?closed
?????*?as?well.
?????*
?????*/
????void?close();

};

1?????????? SocketInputStream類
這個類類似與其他InputStream如FileInputStream類,是InputStream接口類的一個實現(xiàn),執(zhí)行Socket流的讀取操作,實現(xiàn)的接口均是最基礎的操作,如讀取一個byte字節(jié)的數(shù)據(jù),或者讀取指定長度的數(shù)據(jù)。
SocketInputStream類成員和主要接口定義如下:
class?SocketInputStream?:?public?InputStream


{
protected:?

????/**//**
?????*?Pointer?to?the?implementation?of?this?SocketImpl.
?????*/
????PlainSocketImpl?*_impl;?


????/**//**
?????*?Pointer?to?the?implementation?of?this?Socket.
?????*/
????Socket?*_socket;?

????BOOL?_eof;?
BOOL?_closing;


????/**//**
?????*?Creates?a?new?SocketInputStream.?Can?only?be?called
?????*?by?a?Socket.?This?method?needs?to?hang?on?to?the?owner?Socket?so
?????*?that?the?fd?will?not?be?closed.
?????*?@param?impl?the?implemented?socket?input?stream
?????*/
????SocketInputStream(PlainSocketImpl?&impl);

public:?

????/**//**
?????*?Check?current?SocketInputStream?object?if?is?opened.?
?????*
?????*?@return??TRUE?if?opened?else?return?FALSE
?????*/
????BOOL?isOpened();


????/**//**
?????*?Reads?a?byte?of?data?from?this?input?stream.?This?method?blocks
?????*?if?no?input?is?yet?available.
?????*
?????*?@return?????the?next?byte?of?data,?or?<code>-1</code>?if?the?end?of?the
?????*?????????????file?is?reached.
?????*/
????int?read();?


????/**//**
?????*?Reads?up?to?<code>len</code>?bytes?of?data?from?this?input?stream
?????*?into?an?array?of?bytes.?This?method?blocks?until?some?input?is
?????*?available.
?????*
?????*?@param??????b?????the?buffer?into?which?the?data?is?read.
?????*?@param??????off???the?start?offset?of?the?data.
?????*?@param??????len???the?maximum?number?of?bytes?read.
?????*?@return?????the?total?number?of?bytes?read?into?the?buffer,?or
?????*?????????????<code>0</code>?if?there?is?no?more?data?because?the?end?of
?????*?????????????the?file?has?been?reached,?or?-1?if?read?error.
?????*/
????int?read(void?*b,?int?off,?int?len);


????/**//**
?????*?Reads?up?to?<code>len</code>?bytes?of?data?from?this?input?stream
?????*?into?an?array?of?bytes.?This?method?blocks?until?some?input?is
?????*?available.
?????*
?????*?@param??????b?????the?buffer?into?which?the?data?is?read.
?????*?@param??????len???the?maximum?number?of?bytes?read.
?????*?@return?????the?total?number?of?bytes?read?into?the?buffer,?or
?????*?????????????<code>0</code>?if?there?is?no?more?data?because?the?end?of
?????*?????????????the?file?has?been?reached,?or?-1?if?read?error.
?????*/
????int?read(void?*b,?int?len);


????/**//**
?????*?Skips?over?and?discards?<code>n</code>?bytes?of?data?from?the
?????*?input?stream.?The?<code>skip</code>?method?may,?for?a?variety?of
?????*?reasons,?end?up?skipping?over?some?smaller?number?of?bytes,
?????*?possibly?<code>0</code>.?The?actual?number?of?bytes?skipped?is?returned.
?????*
?????*?@param??????n???the?number?of?bytes?to?be?skipped.
?????*?@return?????the?actual?number?of?bytes?skipped.
?????*/
????long?skip(long?n);?


????/**//**
?????*?Returns?the?number?of?bytes?that?can?be?read?from?this?file?input
?????*?stream?without?blocking.
?????*
?????*?@return?????the?number?of?bytes?that?can?be?read?from?this?file?input
?????*?????????????stream?without?blocking.
?????*/
????int?available();?


????/**//**
?????*?Closes?this?file?input?stream?and?releases?any?system?resources
?????*?associated?with?the?stream.
?????*
?????*?<p>?If?this?stream?has?an?associated?channel?then?the?channel?is?closed
?????*?as?well.
?????*/
????void?close();

};

?
1?????????? SocketOutputStream類
這個類類似與其他OutputStream如FileOutputStream類,是OutputStream接口類的一個實現(xiàn),執(zhí)行Socket流的寫操作,實現(xiàn)的接口均是最基礎的操作,如寫一個byte字節(jié)的數(shù)據(jù),或者寫指定長度的數(shù)據(jù)。
SocketOutputStream類成員和主要接口定義如下:
?
class?SocketOutputStream?:?public?OutputStream


{
protected:?

????/**//**
?????*?Pointer?to?the?implementation?of?this?SocketImpl.
?????*/
????PlainSocketImpl?*_impl;?


????/**//**
?????*?Pointer?to?the?implementation?of?this?Socket.
?????*/
Socket?*_socket;


????/**//**
?????*?Creates?a?new?SocketOutputStream.?Can?only?be?called
?????*?by?a?Socket.?This?method?needs?to?hang?on?to?the?owner?Socket?so
?????*?that?the?fd?will?not?be?closed.
?????*?@param?impl?the?implemented?socket?input?stream
?????*/
????SocketOutputStream(PlainSocketImpl?&impl);

public:?

????/**//**
?????*?Check?current?SocketInputStream?object?if?is?opened.?
?????*
?????*?@return??TRUE?if?opened?else?return?FALSE
?????*/
????BOOL?isOpened();?


????/**//**
?????*?Report?position?in?output?stream.
?????*/?
long?tellp();


????/**//**
?????*?Writes?the?specified?byte?to?this?file?output?stream.?Implements?
?????*?the?<code>write</code>?method?of?<code>OutputStream</code>.
?????*
?????*?@param?b???the?byte?to?be?written.
?????*/
????SocketOutputStream&?write(int?b);?


????/**//**
?????*?Writes?<code>len</code>?bytes?from?the?specified?byte?array?
?????*?starting?at?offset?<code>off</code>?to?this?file?output?stream.?
?????*
?????*?@param??????b?????the?data.
?????*?@param??????len???the?number?of?bytes?to?write.
?????*/
????SocketOutputStream&?write(const?void?*b,?int?len);?


????/**//**
?????*?Writes?<code>len</code>?bytes?from?the?specified?byte?array?
?????*?starting?at?offset?<code>off</code>?to?this?file?output?stream.?
?????*
?????*?@param??????b?????the?data.
?????*?@param??????off???the?start?offset?in?the?data.
?????*?@param??????len???the?number?of?bytes?to?write.
?????*/
????SocketOutputStream&?write(const?void?*b,?int?off,?int?len);?


????/**//**
?????*?Flushes?this?output?stream?and?forces?any?buffered?
?????*?output?bytes?to?be?written?out.
?????*/
????void?flush();?


????/**//**
?????*?Closes?this?file?out?stream?and?releases?any?system?resources
?????*?associated?with?the?stream.
?????*
?????*?<p>?If?this?stream?has?an?associated?channel?then?the?channel?is?closed
?????*?as?well.
?????*/
????void?close();

};

?
1?????????? SocketReader類和SocketWriter類
SocketReader類實現(xiàn)了一個對Socket流讀設備即SocketInputStream的讀取器,它實現(xiàn)了Reader接口類的方法,所以具有與其它Reader相同的功能,也可以與其它一些讀操作器如BufferedReader配合使用以達到一些更高級的功能。
SocketWriter 類則實現(xiàn)了一個對Socket流寫設備即SocketOutputStream的寫操作器,它實現(xiàn)了Writer接口類的方法,所以具有與其它Writer相同的功能,如進行一些operator <<運算符的操作等。
詳細例子請參考 httptest.cpp 范例程序。
?
?
?
C++通用框架的設計作者:naven 日期:2006-8-10
?