CSocket
類別
衍生自 CAsyncSocket
,繼承其 Windows Sockets API 的封裝,並表示比 CAsyncSocket
物件更高的抽象層級。
語法
class CSocket : public CAsyncSocket
成員
公用建構函式
名稱 | 描述 |
---|---|
CSocket::CSocket |
建構 CSocket 物件。 |
公用方法
名稱 | 描述 |
---|---|
CSocket::Attach |
將 SOCKET 句柄附加至 CSocket 物件。 |
CSocket::CancelBlockingCall |
取消目前正在進行中的封鎖呼叫。 |
CSocket::Create |
建立套接字。 |
CSocket::FromHandle |
傳回物件的指標 CSocket ,指定句 SOCKET 柄。 |
CSocket::IsBlocking |
判斷封鎖呼叫是否正在進行中。 |
受保護的方法
名稱 | 描述 |
---|---|
CSocket::OnMessagePending |
呼叫 以在等候封鎖呼叫完成時處理暫止訊息。 |
備註
CSocket
與類別 CSocketFile
搭配使用,並 CArchive
管理數據的傳送和接收。
CSocket
物件也提供封鎖,這對 同步作業CArchive
至關重要。 封鎖函式,例如 Receive
、Send
、ReceiveFrom
、SendTo
、 和 Accept
(全部繼承自 CAsyncSocket
),不會在 中CSocket
傳回WSAEWOULDBLOCK
錯誤。 相反地,這些函式會等到作業完成為止。 此外,如果在 CancelBlockingCall
其中一個函式封鎖時呼叫,原始呼叫將會終止並出現錯誤 WSAEINTR。
若要使用 CSocket
物件,請呼叫 建構函式,然後呼叫 Create
以建立基礎 SOCKET
句柄 (類型 SOCKET
)。 建立數據流套接字的預設參數 Create
,但如果您未搭配 CArchive
物件使用套接字,您可以指定參數來建立數據報套接字,或系結至特定埠以建立伺服器套接字。 在客戶端和Accept
伺服器端使用 Connect
連接到用戶端套接字。 然後建立 CSocketFile
物件,並將它與 CSocket
建構函式中的 CSocketFile
對象產生關聯。 接下來,建立對象來傳送,並建立一個 CArchive
接收數據的物件(視需要),然後將它們與 CSocketFile
建構函式中的 CArchive
對象產生關聯。 通訊完成時,終結 CArchive
、 CSocketFile
和 CSocket
物件。 數據類型SOCKET
會在 Windows Sockets:Background 一文中說明。
當您搭配 和 使用 CArchive
時,可能會遇到進入迴圈(byPumpMessages(FD_READ)
)等候要求位元組量的情況CSocket::Receive
。CSocket
CSocketFile
這是因為 Windows 套接字每個通知只允許一個 recv 呼叫 FD_READ
,但 CSocketFile
允許 CSocket
每個 FD_READ
進行多個 recv 呼叫。 如果您在沒有要讀取數據時收到 FD_READ
,則應用程式會停止回應。 如果您從未取得另一個 FD_READ
,應用程式會停止透過套接字進行通訊。
您可以依照下列方式解決此問題。 在套接字類別的 方法中 OnReceive
, CAsyncSocket::IOCtl(FIONREAD, ...)
當您從套接字讀取預期的數據超過一個 TCP 封包的大小時,請先呼叫 Serialize
訊息類別的方法(網路媒體的最大傳輸單位,通常是至少 1096 個字節)。 如果可用數據的大小小於需求,請等候接收所有數據,然後才開始讀取作業。
在下列範例中, m_dwExpected
是用戶預期要接收的大約位元組數目。 假設您在程式代碼的其他地方宣告它。
void CChatSocket::OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
DWORD dwReceived;
if (IOCtl(FIONREAD, &dwReceived))
{
if (dwReceived >= m_dwExpected) // Process only if you have enough data
m_pDoc->ProcessPendingRead();
}
else
{
// Error handling here
}
}
注意
在靜態連結 MFC 應用程式中的次要線程中使用 MFC 套接字時,您必須在每個使用套接字來初始化套接字連結庫的線程中呼叫 AfxSocketInit
。 根據預設, AfxSocketInit
只會在主要線程中呼叫 。
如需詳細資訊,請參閱 MFC 中的 Windows 套接字、Windows 套接字:使用套接字搭配封存、Windows 套接字:使用封存的套接字的方式、Windows 套接字:作業順序、Windows 套接字:使用封存的套接字範例。
繼承階層架構
CSocket
需求
標頭: afxsock.h
CSocket::Attach
呼叫這個成員函式,將句柄附加 hSocket
至 CSocket
物件。
BOOL Attach(SOCKET hSocket);
參數
hSocket
包含套接字的句柄。
傳回值
如果函式成功,則為非零。
備註
句 SOCKET
柄會儲存在對象 m_hSocket
的數據成員中。
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。
範例
class CSockThread : public CWinThread
{
public:
SOCKET m_hConnected;
protected:
CChatSocket m_sConnected;
// remainder of class declaration omitted.
BOOL CSockThread::InitInstance()
{
// Attach the socket object to the socket handle
// in the context of this thread.
m_sConnected.Attach(m_hConnected);
m_hConnected = NULL;
return TRUE;
}
// This listening socket has been constructed
// in the primary thread.
void CListeningSocket::OnAccept(int nErrorCode)
{
UNREFERENCED_PARAMETER(nErrorCode);
// This CSocket object is used just temporarily
// to accept the incoming connection.
CSocket sConnected;
Accept(sConnected);
// Start the other thread.
CSockThread *pSockThread = (CSockThread*)AfxBeginThread(
RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
if (NULL != pSockThread)
{
// Detach the newly accepted socket and save
// the SOCKET handle in our new thread object.
// After detaching it, it should no longer be
// used in the context of this thread.
pSockThread->m_hConnected = sConnected.Detach();
pSockThread->ResumeThread();
}
}
CSocket::CancelBlockingCall
呼叫此成員函式,以取消目前正在進行中的封鎖呼叫。
void CancelBlockingCall();
備註
此函式會取消此套接字的任何未完成封鎖作業。 原始封鎖呼叫會儘快終止,並出現錯誤 WSAEINTR
。
在封鎖 Connect
作業的情況下,Windows Sockets 實作會儘快終止封鎖呼叫,但在連線完成或逾時之前,可能無法釋放套接字資源。只有當應用程式立即嘗試開啟新的套接字(如果沒有套接字可用),或聯機到相同的對等時,這才可能很明顯。
取消以外的 Accept
任何作業可能會使套接字處於不確定狀態。 如果應用程式取消套接字上的封鎖作業,則應用程式唯一可以依賴在套接字上執行的作業是呼叫 Close
,不過其他作業可能在某些 Windows Sockets 實作上運作。 如果您想要應用程式的最大可移植性,您必須小心不要依賴在取消之後執行作業。
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。
CSocket::Create
Create
在建構套接字對象之後呼叫成員函式,以建立 Windows 套接字並附加它。
BOOL Create(
UINT nSocketPort = 0,
int nSocketType = SOCK_STREAM,
LPCTSTR lpszSocketAddress = NULL);
參數
nSocketPort
要與套接字搭配使用的特定埠,如果您想要 MFC 選取埠,則為 0。
nSocketType
SOCK_STREAM
或 SOCK_DGRAM
。
lpszSocketAddress
字串的指標,包含已連線套接字的網路位址,即點數,例如 “128.56.22.8”。 傳遞此參數的NULL字串表示 CSocket
實例應該接聽所有網路介面上的客戶端活動。
傳回值
如果函式成功,則為非零;否則,您可以呼叫 GetLastError
來擷取 0,並擷取特定的錯誤碼。
備註
Create
然後呼叫 Bind
,將套接字系結至指定的位址。 支援下列套接字型態:
SOCK_STREAM
提供循序、可靠、雙向、以連線為基礎的位元組數據流。 針對因特網位址系列使用傳輸控制通訊協定 (TCP)。SOCK_DGRAM
支持數據報,這些數據報是無連接、不可靠的固定緩衝區(通常很小)最大長度。 針對因特網位址系列使用用戶數據報通訊協定 (UDP)。 若要使用此選項,您不得將套接字與 物件搭配CArchive
使用。注意
成員
Accept
函式會採用對新的空白CSocket
物件做為其參數的參考。 您必須先建構這個物件,才能呼叫Accept
。 請記住,如果這個套接字物件超出範圍,連線就會關閉。 請勿呼叫Create
這個新的套接字物件。
如需數據流和數據報套接字的詳細資訊,請參閱 Windows 套接字:背景、Windows 套接字:埠和套接字位址,以及 Windows 套接字:搭配封存使用套接字一文。
CSocket::CSocket
建構 CSocket
物件。
CSocket();
備註
建構之後,您必須呼叫 Create
成員函式。
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。
CSocket::FromHandle
傳回 物件的指標 CSocket
。
static CSocket* PASCAL FromHandle(SOCKET hSocket);
參數
hSocket
包含套接字的句柄。
傳回值
物件的指標CSocket
,如果沒有附加至 hSocket
的物件,NULL
則CSocket
為 。
備註
當指定 SOCKET
句柄時,如果 CSocket
物件未附加至句柄,成員函式會 NULL
傳回且不會建立暫存物件。
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。
CSocket::IsBlocking
呼叫這個成員函式,以判斷封鎖呼叫是否正在進行中。
BOOL IsBlocking();
傳回值
如果套接字封鎖,則為非零;否則為 0。
備註
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。
CSocket::OnMessagePending
覆寫此成員函式以尋找來自 Windows 的特定訊息,並在套接字中回應它們。
virtual BOOL OnMessagePending();
傳回值
如果已處理訊息,則為非零;否則為 0。
備註
這是可覆寫的進階。
當套接字正在提取 Windows 訊息時,架構會呼叫 OnMessagePending
,讓您有機會處理應用程式感興趣的訊息。 如需如何使用 OnMessagePending
的範例,請參閱 Windows 套接字:衍生自套接字類別一文。
如需詳細資訊,請參閱 Windows 套接字:搭配封存使用套接字。