// ChatProjDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "ChatProj.h"
#include "ChatProjDlg.h"
#include "resource.h"
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChatProjDlg 对话框
CChatProjDlg::CChatProjDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChatProjDlg::IDD, pParent)
, m_strMsg(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChatProjDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MESSAGE, m_richEdit);
DDX_Text(pDX, IDC_MESSAGE, m_strMsg);
DDV_MaxChars(pDX, m_strMsg, 200);
DDX_Control(pDX, IDC_MSG_LIST, m_listInfo);
}
BEGIN_MESSAGE_MAP(CChatProjDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_START_BT, &CChatProjDlg::OnBnClickedStartBt)
ON_BN_CLICKED(IDC_EXIT_BT, &CChatProjDlg::OnBnClickedExitBt)
ON_MESSAGE(WM_SOCKET,onSocket)
END_MESSAGE_MAP()
// CChatProjDlg 消息处理程序
long CChatProjDlg::onSocket(WPARAM wParam,LPARAM lParam)
{
SOCKET s = wParam;
if (WSAGETSELECTERROR(lParam))
{
removeClient(s);
closesocket(s);
return 0;
}
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT://有连入
if(m_nClient {
SOCKET client = ::accept(s,NULL,NULL);
//设置新套接字的窗口通知类型
int i = ::WSAAsyncSelect(client,m_hWnd,WM_SOCKET,FD_ACCEPT|FD_WRITE|FD_CLOSE);
addClient(client);
/*::send(client,"aaa",4,0);*/
}
else
{
MessageBox(L"客满!");
}
break;
case FD_CLOSE:
removeClient(s);
::closesocket(s);
break;
case FD_READ://接受发过来的数据包
sockaddr_in sockAddr;
int nSocketAddrLen = sizeof(sockAddr);
memset(&sockAddr,0,nSocketAddrLen);
::getpeername(s,(SOCKADDR*)&sockAddr,&nSocketAddrLen);
//转化为主机字节
int nPeerPort = ::ntohs(sockAddr.sin_port);
DWORD dwIP = ::inet_addr(::inet_ntoa(sockAddr.sin_addr));
HOSTENT *pHost = ::gethostbyaddr((LPSTR)&dwIP,4,AF_INET);
char szHostName[256];
strncpy_s(szHostName,pHost->h_name,sizeof(pHost->h_name));
char szText[1024]={0};
::recv(s,szText,1024,0);
//CString strItem = CString(szHostName)+"["+::inet_ntoa(sockAddr.sin_addr)+"]:"+CString(szText);
m_listInfo.InsertString(0,CString(szText));
m_listInfo.AddString(L"aa");
break;
}
return 0;
}
BOOL CChatProjDlg::OnInitDialog()
{
CDialog::OnInitDialog();
USES_CONVERSION;
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP,CRect(0,0,0,0),this,101);
m_bar.SetBkColor(RGB(0xa6,0xca,0xf0));
int arWidth[]={200,-1};
m_bar.SetParts(2,arWidth);
m_bar.SetText(L"私人聊天",1,0);
//m_bar.SetText(L"空闲",0,0);
//设置列表框控件到m_listInfo的关联
m_nClient = 0;
m_socket = INVALID_SOCKET ;
char szHost[256];
//取得本机名称
::gethostname(szHost,256);
//取得地址信息
HOSTENT *pHost = gethostbyname(szHost);
if (pHost != NULL)
{
CString sIp;
wchar_t *ch;
// get first ip addr
in_addr *addr = (in_addr*) *(pHost->h_addr_list);
ch = A2W(inet_ntoa(addr[0]));
sIp.Format(L"本机IP:%s",ch);
m_bar.SetText(sIp,0,0);
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CChatProjDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// 使图标在工作矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标显示。
//
HCURSOR CChatProjDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
BOOL CChatProjDlg::createAndListen(int nPort)
{
if (m_socket !=INVALID_SOCKET)
{
::closesocket(m_socket);
}
m_socket = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (m_socket == INVALID_SOCKET)
{
return FALSE;
}
//
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(nPort);
sin.sin_addr.s_addr = INADDR_ANY;
//bind port
if (::bind(m_socket,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR)
{
return FALSE;
}
//设置为窗口通知类型
WSAAsyncSelect( m_socket,m_hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);
//进入监听
::listen(m_socket,5);
return TRUE;
}
BOOL CChatProjDlg::addClient(SOCKET s)
{
if (m_nClient < MAX_SOCKET)
{
m_arClient[m_nClient++] = s;
return TRUE;
}
return FALSE;
}
void CChatProjDlg::removeClient(SOCKET s)
{
BOOL bFind = FALSE;
int nIndex = 0;
for(int i = 0;i {
if (m_arClient[i] == s)
{
bFind =TRUE;
nIndex = i;
break;
}
}
if (bFind)
{
m_nClient--;
for (int j = nIndex;j < m_nClient;j++)
{
m_arClient[j] = m_arClient[j+1];
}
}
}
void CChatProjDlg::closeAllSocket()
{
if (m_socket != INVALID_SOCKET)
{
::closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
for (int i = 0;i < m_nClient;i++)
{
::closesocket(m_arClient[i]);
}
m_nClient =0;
}
void CChatProjDlg::OnBnClickedStartBt()
{
//开启服务
if (m_socket == INVALID_SOCKET)
{
CString sPort;
GetDlgItem(IDC_PORT_ED)->GetWindowText(sPort);
int nPort =_wtoi(sPort.GetBuffer());
if (nPort <1||nPort> 65535)
{
MessageBox(L"端口号错误!");
return;
}
if (!createAndListen(nPort))
{
MessageBox(L"启动服务出错");
return;
}
GetDlgItem(IDC_START_BT)->SetWindowText(L"停止服务");
m_bar.SetText(L"正在监听。。。。。",0,0);
GetDlgItem(IDC_PORT_ED)->EnableWindow(FALSE);
}
else
{
closeAllSocket();
GetDlgItem(IDC_START_BT)->SetWindowText(L"开启服务");
m_bar.SetText(L"空闲",0,0);
GetDlgItem(IDC_PORT_ED)->EnableWindow(TRUE);
}
}
void CChatProjDlg::OnBnClickedExitBt()
{
closeAllSocket();
CDialog::OnCancel();
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12560256/viewspace-442242/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12560256/viewspace-442242/