MFC CSocket

头文件

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 _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif
};

CAsyncSocket类定义

// CAsyncSocket

class CAsyncSocket : public CObject
{
	DECLARE_DYNAMIC(CAsyncSocket);
private:
	CAsyncSocket(const CAsyncSocket& rSrc);    // no implementation
	void 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 _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
	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();

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值