今天我们用CSocket实现昨天用SOCKET实现的异步套接字的功能吧.
如果你还是不知道怎么实现用户自定义消息的话,你也不用急.今天,我们并不需要用自定义消息的,我们只需要从CSOCKET来派生我们对SOCKET的实现就行了.我们先来讲讲实现流程吧:
首先,创建套接字 - 绑定端口 - 发送/接受数据. - 关闭套接字
好,我们就沿着这个这个轨迹来写吧.
首先,我们派生一个我们的CMySocket:代码如下:
头文件:
#if !defined(AFX_MYSOCKET_H__556DCBE5_E9F7_4285_A0F9_3B30A9CABB6D__INCLUDED_)
#define AFX_MYSOCKET_H__556DCBE5_E9F7_4285_A0F9_3B30A9CABB6D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MySocket.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CMySocket command target
class CMySocket : public CSocket
{
// Attributes
public:
HWND m_hWnd;
CString m_strHost;
CString m_strSend;
CString m_strRecv;
// Operations
public:
CMySocket();
virtual ~CMySocket();
public:
// Overrides
public:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMySocket)
public:
virtual void OnSend(int nErrorCode);
virtual void OnReceive(int nErrorCode);
//}}AFX_VIRTUAL
// Generated message map functions
//{{AFX_MSG(CMySocket)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
// Implementation
protected:
private:
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MYSOCKET_H__556DCBE5_E9F7_4285_A0F9_3B30A9CABB6D__INCLUDED_)
实现文件:
// MySocket.cpp : implementation file
//
#include "stdafx.h"
#include "MFCCSocket.h"
#include "MySocket.h"
#include "MFCCSocketDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMySocket
CMySocket::CMySocket()
{
m_strHost = _T("");
m_strSend = _T("");
m_strRecv = _T("");
}
CMySocket::~CMySocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CMySocket, CSocket)
//{{AFX_MSG_MAP(CMySocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CMySocket member functions
void CMySocket::OnSend( int nErrorCode )
{
CSocket::OnSend( nErrorCode );
static int i = 0;
if ( i == 0 )
{
i = 1; return ;
}
char buffer[MAX_PATH] = {0};
SOCKADDR_IN addrTo;
HOSTENT * pHost = NULL;
int nLen,nRet;
nLen = sizeof(SOCKADDR);
pHost = gethostbyname( m_strHost );
addrTo.sin_addr.S_un.S_addr = *((DWORD*)pHost->h_addr_list[0]);
addrTo.sin_family = AF_INET;
addrTo.sin_port = htons(4443);
memset( addrTo.sin_zero, 0, sizeof(addrTo.sin_zero) );
m_strSend += "/t/t/t/t";
do
{
strncpy( buffer, m_strSend, MAX_PATH - 1 );
nRet = ( buffer, strlen(buffer), (SOCKADDR*)&addrTo, nLen );
if( SOCKET_ERROR == nRet )
{
sprintf( buffer, "发送数据失败!有可能出现数据丢失!/n错误原因:%d", GetLastError() );
AfxMessageBox( buffer );
break ;
}
buffer[nRet] = 0;
m_strSend.Delete( 0, nRet );
if ( m_strSend.GetLength() <= 0 ) break ;
memset( buffer, 0, MAX_PATH );
} while( TRUE );
m_strSend = _T("");
}
void CMySocket::OnReceive( int nErrorCode )
{
CString strRecv = _T("");
char buffer[MAX_PATH] = {0};
SOCKADDR_IN addrFrom;
HOSTENT * pHost = NULL;
int nLen,nRet;
nLen = sizeof(SOCKADDR);
do
{
nRet = ReceiveFrom( buffer, MAX_PATH, (SOCKADDR*)&addrFrom, &nLen );
if( SOCKET_ERROR == nRet )
{
sprintf( buffer, "接收数据失败!错误原因:%d", GetLastError() );
AfxMessageBox( buffer );
return ;
}
buffer[nRet] = 0; strRecv += buffer;
if ( strRecv.Find("/t/t/t/t") >= 0 )
{
strRecv.Replace( _T("/t/t/t/t"), _T("/r/n" ) );
break;
}
memset( buffer, 0, MAX_PATH );
} while( TRUE );
pHost = gethostbyaddr( (char*)&addrFrom.sin_addr.S_un.S_addr, 4, AF_INET );
m_strRecv.Format("%s(%s) : /r/n%s",pHost->h_name, inet_ntoa(addrFrom.sin_addr), strRecv );
int nPos,nMin,nMax;
((CMFCCSocketDlg*)CWnd::FromHandle(m_hWnd))->GetDlgItem(IDC_EDIT_STRING)->GetWindowText( strRecv );
nPos = strRecv.GetLength();
strRecv += m_strRecv;
((CMFCCSocketDlg*)CWnd::FromHandle(m_hWnd))->GetDlgItem(IDC_EDIT_STRING)->SetWindowText( strRecv );
((CMFCCSocketDlg*)CWnd::FromHandle(m_hWnd))->GetDlgItem(IDC_EDIT_STRING)->GetScrollRange ( SB_VERT, &nMin, &nMax );
((CMFCCSocketDlg*)CWnd::FromHandle(m_hWnd))->GetDlgItem(IDC_EDIT_STRING)->SetScrollPos ( SB_VERT, nMax, TRUE );
((CEdit*)((CMFCCSocketDlg*)CWnd::FromHandle(m_hWnd))->GetDlgItem(IDC_EDIT_STRING))->SetSel( nPos,strRecv.GetLength() );
m_strRecv = _T("");
CSocket::OnReceive( nErrorCode );
}
好了,这就是我们的CMySocket了.我们来用我们的套接字来创建并绑定吧:(BOOL CMFCCSocketDlg::OnInitDialog()中实现)
char buffer[MAX_PATH] = {0};
if( !m_Socket.Create( 4443, SOCK_DGRAM,NULL ) )
{
sprintf( buffer, "创建套接字失败!错误原因:%d", GetLastError() );
MessageBox( buffer );
PostQuitMessage(0);
}
m_Socket.m_hWnd = m_hWnd;
接着,我们就要实现发送接收数据了,实际上在我们重载CSOCKET的时候,我们已经实现了发送接收的代码了.而且这里实现的接受和发送是没有长度限制的(精华哦!).
好,我们就来看看我是怎么来发送的(接收是自动接收,不需要再处理了,因为在重载的时候已经实现了这个虚函数了.)
void CMFCCSocketDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
UpdateData();
char buffer[MAX_PATH] = {0};
HOSTENT *pHost = NULL;
m_Socket.m_strHost = m_strHost;
m_Socket.m_strSend = m_strSend;
if ( m_strHost.GetLength() <= 0 )
{
MessageBox( _T("请填写主机地址!") );
return ;
}
if ( m_strSend.GetLength() <= 0 )
{
MessageBox( _T("发送消息不能为空!") );
return ;
}
pHost = gethostbyname( m_strHost );
if ( !pHost )
{
sprintf( buffer, "无法解析服务器地址!错误原因:%d", WSAGetLastError() );
MessageBox( buffer );
return ;
}
m_Socket.OnSend(0);
m_strSend = _T("");
UpdateData(FALSE);
}
接着,不就是关闭了嘛.实际上,你不需要显示的关闭它,它会在销毁的时候自动关闭的.呵呵.就写到这了.
看不懂那就没办法了哦!