头文件
afxsock.h
AfxSocketInit() 函数必须在使用socket之前实现
继承关系
class CSocket : public CAsyncSocket
class CAsyncSocket : public CObject
客户端
- 构造一个CSocket对象。
- 使用该对象调用Create函数创建底层SOCKET句柄,因为客户端不需要绑定任何端口和地址, 所以用默认参数即可
- 调用Connect函数将套接字对象连接到服务器套接字,指定服务器地址和端口号
流程:
socket()
create()
connect()
receive() / send()
close()
代码实现:
// 初始化
AfxSocketInit();
// 创建 CSocket 对象
CSocket aSocket;// 初始化 CSocket 对象, 因为客户端不需要绑定任何端口和地址, 所以用默认参数即可
if ( ! aSocket.Create())
{char szMsg[1024] = {0};sprintf(szMsg, "create faild: %d", aSocket.GetLastError());AfxMessageBox(szMsg);return;
}// 连接指定的地址和端口
if (aSocket.Connect(strIP, nPort))
{char szRecValue[1024] = {0};//发送内容给服务器aSocket.Send(strText, strText.GetLength());//接收服务器发送回来的内容(该方法会阻塞, 在此等待有内容接收到才继续向下执行)aSocket.Receive((void *)szRecValue, 1024);AfxMessageBox(szRecValue);
}
else
{char szMsg[1024] = {0}; sprintf(szMsg, "create faild: %d", aSocket.GetLastError()); AfxMessageBox(szMsg);
}
// 关闭
aSocket.Close();
服务端
- 构造一个CSocket对象。
- 使用该对象调用Create函数创建底层SOCKET句柄,在Create调用中指定端口(不需要再调用bind函数,因为create中已经调用bind),或者直接使用bind函数,指定端口
- 调用Listen开始监听来自客户端的连接尝试。收到连接请求后,通过调用Accept接受它。
流程:
socket()
bind() or create()
listen()
accept()
receive() / send()
close()
注意:
使用Create创建,因为容易会出现10048错误
解决方案:
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
//设置Socket的选项, 解决10048错误必须的步骤
aSocket.SetSockOpt(SO_REUSEADDR, ( void * ) & bOptVal, bOptLen, SOL_SOCKET);
代码实现:
//初始化Winscok
if (!AfxSocketInit())
{AfxMessageBox(IDP_SOCKETS_INIT_FAILED);return 1;
}//socket------------------------------------------------
CSocket aSocket, serverSocket;
//调用Socket函数,最好不要使用aSocket.Create创建,因为容易会出现10048错误
if (!aSocket.Socket())
{char szError[256] = {0}; sprintf(szError, "Create Faild: %d", GetLastError()); AfxMessageBox(szError); return 1;
}
//绑定端口
if (!aSocket.Bind(nPort))
{char szError[256] = {0}; sprintf(szError, "Bind Faild: %d", GetLastError()); AfxMessageBox(szError); return 1;
}
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
//设置Socket的选项, 解决10048错误必须的步骤
aSocket.SetSockOpt(SO_REUSEADDR, ( void * ) & bOptVal, bOptLen, SOL_SOCKET);
//监听
if ( ! aSocket.Listen( 10 ))
{ char szError[256] = {0}; sprintf(szError, "Listen Faild: %d", GetLastError()); AfxMessageBox(szError);return 1;
}//接收外部连接
if(!aSocket.Accept(serverSocket))
{return 1;
}char szRecvMsg[256] = {0};
//接收客户端内容:阻塞
serverSocket.Receive(szRecvMsg, 256);
//发送内容给客户端
serverSocket.Send("Have Receive The Msg", 50);//关闭
aSocket.Close();
serverSocket.Close();
CSocket类定义
// CSocket头文件定义class CSocket : public CAsyncSocket
{DECLARE_DYNAMIC(CSocket);
private:CSocket(const CSocket& rSrc); // 没有实现void operator=(const CSocket& rSrc); // 没有实现// 构造
public:CSocket();BOOL Create(UINT nSocketPort = 0, int nSocketType=SOCK_STREAM,LPCTSTR lpszSocketAddress = NULL);// Attributes
public:BOOL IsBlocking();static CSocket* PASCAL FromHandle(SOCKET hSocket);BOOL Attach(SOCKET hSocket);// Operations
public:void CancelBlockingCall();// Overridable callbacks
protected:virtual BOOL OnMessagePending();// Implementation
public:int m_nTimeOut;virtual ~CSocket();static int PASCAL ProcessAuxQueue();virtual BOOL Accept(CAsyncSocket& rConnectedSocket,SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL);virtual void Close();virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);virtual int Send(const void* lpBuf, int nBufLen, int nFlags = 0);int SendChunk(const void* lpBuf, int nBufLen, int nFlags);protected:friend class CSocketWnd;BOOL* m_pbBlocking;int m_nConnectError;virtual BOOL ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen);virtual int ReceiveFromHelper(void* lpBuf, int nBufLen,SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags);virtual int SendToHelper(const void* lpBuf, int nBufLen,const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags);static void PASCAL AuxQueueAdd(UINT message, WPARAM wParam, LPARAM lParam);virtual BOOL PumpMessages(UINT uStopFlag);#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;
#endif
};
CAsyncSocket类定义
// CAsyncSocketclass CAsyncSocket : public CObject
{DECLARE_DYNAMIC(CAsyncSocket);
private:CAsyncSocket(const CAsyncSocket& rSrc); // no implementationvoid operator=(const CAsyncSocket& rSrc); // no implementation// Construction
public:CAsyncSocket();BOOL Create(UINT nSocketPort = 0, int nSocketType=SOCK_STREAM,long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,LPCTSTR lpszSocketAddress = NULL);BOOL CreateEx(ADDRINFOT* pAI, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);// Attributes
public:SOCKET m_hSocket;operator SOCKET() const;BOOL Attach(SOCKET hSocket, long lEvent =FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);SOCKET Detach();BOOL GetPeerName(CString& rPeerAddress, UINT& rPeerPort);BOOL GetPeerName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);BOOL GetPeerNameEx(CString& rPeerAddress, UINT& rPeerPort); BOOL GetSockName(CString& rSocketAddress, UINT& rSocketPort);BOOL GetSockName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);BOOL GetSockNameEx(CString& rSocketAddress, UINT& rSocketPort);BOOL SetSockOpt(int nOptionName, const void* lpOptionValue,int nOptionLen, int nLevel = SOL_SOCKET);BOOL GetSockOpt(int nOptionName, void* lpOptionValue,int* lpOptionLen, int nLevel = SOL_SOCKET);static CAsyncSocket* PASCAL FromHandle(SOCKET hSocket);static int PASCAL GetLastError();// Operations
public:virtual BOOL Accept(CAsyncSocket& rConnectedSocket,SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL);BOOL Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress = NULL);BOOL Bind (const SOCKADDR* lpSockAddr, int nSockAddrLen);BOOL BindEx(ADDRINFOT* pAI);virtual void Close();BOOL Connect(LPCTSTR lpszHostAddress, UINT nHostPort);BOOL Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen);BOOL ConnectEx(ADDRINFOT* pAI);BOOL IOCtl(long lCommand, DWORD* lpArgument);BOOL Listen(int nConnectionBacklog=5);virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);int ReceiveFrom(void* lpBuf, int nBufLen,CString& rSocketAddress, UINT& rSocketPort, int nFlags = 0);int ReceiveFrom(void* lpBuf, int nBufLen,SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags = 0);int ReceiveFromEx(void* lpBuf, int nBufLen,CString& rSocketAddress, UINT& rSocketPort, int nFlags = 0);enum { receives = 0, sends = 1, both = 2 };BOOL ShutDown(int nHow = sends);virtual int Send(const void* lpBuf, int nBufLen, int nFlags = 0);int SendTo(const void* lpBuf, int nBufLen,UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0);int SendTo(const void* lpBuf, int nBufLen,const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags = 0);int SendToEx(const void* lpBuf, int nBufLen,UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0);BOOL AsyncSelect(long lEvent =FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);// Overridable callbacks
protected:virtual void OnReceive(int nErrorCode);virtual void OnSend(int nErrorCode);virtual void OnOutOfBandData(int nErrorCode);virtual void OnAccept(int nErrorCode);virtual void OnConnect(int nErrorCode);virtual void OnClose(int nErrorCode);// Implementation
public:virtual ~CAsyncSocket();static CAsyncSocket* PASCAL LookupHandle(SOCKET hSocket, BOOL bDead = FALSE);static void PASCAL AttachHandle(SOCKET hSocket, CAsyncSocket* pSocket, BOOL bDead = FALSE);static void PASCAL DetachHandle(SOCKET hSocket, BOOL bDead = FALSE);static void PASCAL KillSocket(SOCKET hSocket, CAsyncSocket* pSocket);static void PASCAL DoCallBack(WPARAM wParam, LPARAM lParam);BOOL Socket(int nSocketType=SOCK_STREAM, long lEvent =FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,int nProtocolType = 0, int nAddressFormat = PF_INET);#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;
#endifprotected:friend class CSocketWnd;virtual BOOL ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen);virtual int ReceiveFromHelper(void* lpBuf, int nBufLen,SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags);virtual int SendToHelper(const void* lpBuf, int nBufLen,const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags);
};
流程说明
序号 |
服务端 |
客户端 |
1 |
构造一个套接字 CAsyncSocket sockServer |
构造一个套接字 CAsyncSocket sockClient |
2 |
创建SOCKET句柄,绑定到指定的端口 sockServer.Create(nPort); |
创建SOCKET句柄,使用默认参数 sockClient.Create(); |
3 |
启动监听,时刻准备接收连接请求 sockServer.Listen(); |
|
4 |
请求链接服务器 sockClient.Connect(strAddress,nPort) |
|
5 |
构造一个新的空套接字 CAsyncSocket sockRecv; 接收连接 sockServer.Accept(sockRecv); |
|
6 |
接收数据 sockRecv.Receive(pBuffer,nLen); |
发送连接 sockClient.Send(pBuffer,nLen); |
7 |
发送数据 sockRecv.Send(pBuffer,nLen); |
接收数据 sockClient.Receive(pBuffer,nLen); |
8 |
关闭套接字对象 sockRecv.Close(); |
关闭套接字对象 sockClient.Close(); |