当前位置: 代码迷 >> 综合 >> MFC CSocket
  详细解决方案

MFC CSocket

热度:99   发布时间:2023-10-31 05:46:03.0

头文件

afxsock.h

AfxSocketInit() 函数必须在使用socket之前实现

继承关系

class CSocket : public CAsyncSocket

class CAsyncSocket : public CObject

客户端

  1. 构造一个CSocket对象。
  2. 使用该对象调用Create函数创建底层SOCKET句柄,因为客户端不需要绑定任何端口和地址, 所以用默认参数即可
  3. 调用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();

服务端

  1. 构造一个CSocket对象。
  2. 使用该对象调用Create函数创建底层SOCKET句柄,在Create调用中指定端口(不需要再调用bind函数,因为create中已经调用bind),或者直接使用bind函数,指定端口
  3. 调用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();

  相关解决方案