mfc socket 编程的流程是怎么样的?

mfc socket 编程的流程是怎么样的?,第1张

初始化socket

首先需要调用AfxSocketInit()函数来初始化我们的socket环境。

为了初始化sockets,我们需要调用AfxSocketInit()函数。它通常是在MFC中的InitInstance()函数中被调用的。如果我们用程序向导来创建socket程序的话,查看“use Windows Sockets”这个选项,然后选中它。它将会自动的为我们创建这个步骤了。(如果我们没有选中这个选项的话,我们也可以手动添加这些代码的。)这个函数的返回值显示这个函数的调用成功或失败。

BOOL CServerApp::InitInstance()

{....

if( AfxSocketInit() == FALSE)

{

AfxMessageBox("Sockets Could Not Be Initialized")

return FALSE

}

...

}

创建Server Sockets

为了创建一个Server Socket,我们需要声明一个CAyncSocket的变量或者我们自己定制的一个从AyncSocket或是Cscket继承来的类的类型的变量。然后调用Create()函数,同时指定监听的端口。这个函数的返回值显示这个函数的调用成功或失败。

UpdateData(TRUE)

m_sListener.Create(m_port)

if(m_sListener.Listen()==FALSE)

{

AfxMessageBox("Unable to Listen on that port,please try another port")

m_sListener.Close()

return

}

创建Client Sockets

为了创建Client socket类,我们需要声明一个CAyncSocket的变量或者我们自己定制的一个从AyncSocket或是Cscket继承来的类的类型的变量。然后调用Create()函数,同时指定监听的端口。这个函数的返回值显示这个函数的调用成功或失败。

m_sConnected.Create()

m_sConnected.Connect("server ip",port)

监听客户端的连接

创建了server socket以后,我们要进行监听。调用Listen()函数。这个函数的返回值显示这个函数的调用成功或失败。

if( m_sListener.Listen()== FALSE)

{

AfxMessageBox("Unable to Listen on that port,please try another port")

m_sListener.Close()

return

}

接受连接

连接请求要被接受accept,是用另外的socket,不是正在监听的socket。请参看代码。

void CXXXDlg::OnAccept()

{

CString strIP

UINT port

if(m_sListener.Accept(m_sConnected))

{

m_sConnected.GetSockName(strIP,port)//应该是GetPeerName,获取对方的IP和port

m_status="Client Connected,IP :"+ strIP

m_sConnected.Send("Connected To Server",strlen("Connected To Server"))

UpdateData(FALSE)

}

else

{

AfxMessageBox("Cannoot Accept Connection")

}

}

发送数据

数据放在一个buffer中或是结构体中,调用send()函数发送。

m_sConnected.Send(pBuf,iLen)

接受数据

调用receive()接受数据。

void CXXXrDlg::OnReceive()

{

char *pBuf =new char [1025]

CString strData

int iLen

iLen=m_sConnected.Receive(pBuf,1024)

if(iLen == SOCKET_ERROR)

{

AfxMessageBox("Could not Recieve")

}

else

{

pBuf[iLen]=NULL

strData=pBuf

m_recieveddata.Insert(m_recieveddata.GetLength(),strData)

//display in server

UpdateData(FALSE)

m_sConnected.Send(pBuf,iLen) //send the data back to the Client

delete pBuf

}

}

关闭连接

m_sConnected.ShutDown(0) 停止发送数据

m_sConnected.ShutDown(1) 停止接受数据

m_sConnected.ShutDown(2) 停止发送接受数据

m_sConnected.Close()

编写自己的socket类

在class view中选择添加一个新类,设置它的基类为CAsyncSocket,在类向导的帮助下添加如下的一些函数。

class MySocket : public CAsyncSocket

{ // Attributes

public:

// Operations

public:

MySocket()

virtual ~MySocket()

// Overrides

public:

void SetParentDlg(CDialog *pDlg)// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(MySocket)

public:

virtual void OnAccept(int nErrorCode)

virtual void OnClose(int nErrorCode)

virtual void OnConnect(int nErrorCode)

virtual void OnOutOfBandData(int nErrorCode)

virtual void OnReceive(int nErrorCode)

virtual void OnSend(int nErrorCode)

//}}AFX_VIRTUAL // Generated message map functions

//{{AFX_MSG(MySocket)

// NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG

protected:

private:

CDialog * m_pDlg

}

设置“Parent Dialog”

调用这个socket类的SetParentDlg函数,保证当socket事件发生的时候这个窗体能接收到。

m_sListener.SetParentDlg(this)

m_sConnected.SetParentDlg(this)

建立Socket 事件和窗体成员函数之间的联系

在这个窗体类中添加一些函数,比如void OnReceive()void OnClose()void OnAccept()void OnConnect()等,它们会在我们编写的的socket类中调用到。

void MySocket::OnAccept(int nErrorCode)

{

// TODO: Add your specialized code here and/or call the base class

if(nErrorCode==0)

{

((CServerDlg*)m_pDlg)->OnAccept()

}

CAsyncSocket::OnAccept(nErrorCode)

}

这个源码有个错误,是这个地方 char *buff[256]是256个指针,每个指针大小为4个字节,并且指向位置不确定,buff就是指向指针的指针,而不是指向空间的。应该为char buff[256]是256个字符空间 buff就是空间的首地址,也就指针,如果不改的话Receive( buff,256)就出错了。

=(struct MEG*)buff

就是强制类型转换,将MEG指针 指向了 buff位置,利用MEG结构分组buff指向的内容。虽然buff是256但MEG大小之外的通过MEG指针访问不到。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11708443.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存