socket 开发

// 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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值