servertestdlg.cpp

来自「简单的聊天程序」· C++ 代码 · 共 419 行

CPP
419
字号
// ServerTestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ServerTest.h"
#include "ServerTestDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerTestDlg dialog

CServerTestDlg::CServerTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CServerTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CServerTestDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CServerTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CServerTestDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CServerTestDlg, CDialog)
	//{{AFX_MSG_MAP(CServerTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_CLIENT_ACCEPT,OnMyAccept)
	ON_MESSAGE(WM_CLIENT_MESSAGE,OnMyMessage)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerTestDlg message handlers
CString CServerTestDlg::GetMyLastError()
{
	CString strError="";
	int nError=WSAGetLastError();
	switch(nError)
	{
	case WSANOTINITIALISED:
		{
			strError=_T("A successful WSAStartup must occur before using this FUNCTION");
		}
		break;
	case WSAENETDOWN:
		{
			strError=_T("The network subsystem has failed.");
		}
		break;
	case WSAEFAULT:
		{
			strError=_T("The addrlen parameter is too small or addr is not a valid part of the user address space.");
		}
		break;
	case WSAEINTR:
		{
			strError=_T("A blocking Windows Sockets 1.1 call was canceled through WSACancelBlockingCall.");
		}
		break;
	case WSAEINPROGRESS:
		{
			strError=_T("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. ");
		}
		break;
	case WSAEINVAL:
		{
			strError=_T("The listen function was not invoked prior to accept.");
		}
		break;
	case WSAEMFILE:
		{
			strError=_T("The queue is nonempty upon entry to accept and there are no descriptors available. ");
		}
		break;
	case WSAENOBUFS:
		{
			strError=_T("No buffer space is available. ");
		}
		break;
	case WSAENOTSOCK:
		{
			strError=_T("The descriptor is not a socket. ");
		}
		break;
	case WSAEOPNOTSUPP:
		{
			strError=_T("The referenced socket is not a type that supports connection-oriented service. ");
		}
		break;
	case WSAEWOULDBLOCK:
		{
			strError=_T("The socket is marked as nonblocking and no connections are present to be accepted");
		}
		break;
	default:
		{
			strError=_T("unknown error");
		}
		break;
	}

	return strError;
}
BOOL CServerTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_bStart=FALSE;
	m_server=INVALID_SOCKET;
	m_client=INVALID_SOCKET;
	Start();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CServerTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CServerTestDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CServerTestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CServerTestDlg::AddMessageToMessageBar(CString strMessage)
{
	CString str;
	GetDlgItemText(IDC_MESSAGE_EDIT,str);
	str=strMessage+"\r\n"+str;
	SetDlgItemText(IDC_MESSAGE_EDIT,str);
}

void CServerTestDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	if(m_bStart)
	{
		closesocket(m_server);
		closesocket(m_client);
	}
	WSACleanup();
}

BOOL CServerTestDlg::Start()
{
	WSADATA wsData;
	WORD	version=MAKEWORD(2,2);
	if(WSAStartup(version,&wsData))
	{
		AddMessageToMessageBar("start up fail");
		WSACleanup();
		return FALSE;
	}
	if(version!=wsData.wVersion)
	{
		AddMessageToMessageBar("version not right!");
		WSACleanup();
		return FALSE;
	}
	m_server=socket(PF_INET,SOCK_STREAM,0);
	if(m_server==INVALID_SOCKET)
	{
		AddMessageToMessageBar("socket create fail!");
		WSACleanup();
		return FALSE;
	}
	
	memset((void*)&server_addr,0,sizeof(SOCKADDR));
	server_addr.sin_family=AF_INET;
	server_addr.sin_addr.s_addr=inet_addr(IP);
	server_addr.sin_port=htons(PORT);

	int error;
	error=bind(m_server,(LPSOCKADDR)&server_addr,sizeof(SOCKADDR));
	if(SOCKET_ERROR==error)
	{
		AddMessageToMessageBar("bind error!");
		WSACleanup();
		return FALSE;
	}
	error=WSAAsyncSelect(m_server,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);
	if(SOCKET_ERROR==error)
	{
		AddMessageToMessageBar("select event error!");
		WSACleanup();
		return FALSE;
	}
	error=listen(m_server,1);
	if(SOCKET_ERROR==error)
	{
		AddMessageToMessageBar("listen error!");
		WSACleanup();
		return FALSE;
	}

	m_bStart=TRUE;
	AddMessageToMessageBar("open success!");
	return TRUE;
}
LRESULT	CServerTestDlg::OnMyAccept(WPARAM wParam,LPARAM lParam)
{
	if(m_client!=INVALID_SOCKET)
	{
		AddMessageToMessageBar("already have a client!");
		return 1L;
	}
	if(WSAGETSELECTERROR(lParam))
	{
		AddMessageToMessageBar("occer a accept error!");
		return 1L;
	}
	if(WSAGETSELECTEVENT(lParam)!=FD_ACCEPT)
	{
		AddMessageToMessageBar("is not selected event!");
		return 1L;
	}

	m_client_addr_len=sizeof(SOCKADDR);
	memset((void*)&client_addr,0,sizeof(SOCKADDR));
	m_client=accept(m_server,(LPSOCKADDR)&client_addr,&m_client_addr_len);
	if(m_client==INVALID_SOCKET)
	{
		AddMessageToMessageBar(GetMyLastError());
		AddMessageToMessageBar("accept a error socket!");
		return 1L;
	}

	int error=WSAAsyncSelect(m_client,m_hWnd,WM_CLIENT_MESSAGE,FD_READ|FD_CLOSE);
	if(SOCKET_ERROR==error)
	{
		closesocket(m_client);
		m_client=INVALID_SOCKET;
		AddMessageToMessageBar("client select event fail!");
		return 1L;
	}

	UINT port=ntohs(client_addr.sin_port);
	CString ip=inet_ntoa(client_addr.sin_addr);

	CString str;
	str.Format("一个用户加入:ip=[%s],port=[%u]",ip,port);
	AddMessageToMessageBar(str);
	return 0L;
}
LRESULT	CServerTestDlg::OnMyMessage(WPARAM wParam,LPARAM lParam)
{
	if(WSAGETSELECTERROR(lParam))
	{
		AddMessageToMessageBar("occer a accept error!");
		return 1L;
	}
	if(WSAGETSELECTEVENT(lParam)==FD_CLOSE)
	{
		if(m_client==(SOCKET)wParam)
		{
			closesocket(m_client);
			m_client=INVALID_SOCKET;

			UINT port=ntohs(client_addr.sin_port);
			CString ip=inet_ntoa(client_addr.sin_addr);
			CString str;
			str.Format("用户退出了:ip=[%s],port=[%u]",ip,port);
			AddMessageToMessageBar(str);
		}
		else
		{
			AddMessageToMessageBar("不是在线的用户退出消息");
		}
	}
	else if(WSAGETSELECTEVENT(lParam)==FD_READ)
	{
		char szBuffer[1024]={0};
		if(m_client==(SOCKET)wParam)
		{
			int len=recv(m_client,szBuffer,1024,0);
			if(SOCKET_ERROR==len)
			{
				AddMessageToMessageBar("读取数据错误!");
			}
			else if(0==len)
			{
				AddMessageToMessageBar("读到一个0字节");
			}
			else
			{
				UINT port=ntohs(client_addr.sin_port);
				CString ip=inet_ntoa(client_addr.sin_addr);
				CString str;
				str.Format("接收到数据:ip=[%s],port=[%u][%s][%d]",ip,port,szBuffer,len);
				AddMessageToMessageBar(str);
			}
		}
	}
	return 0L;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?