WINDOWS平臺下的SOCKET聊天程序

上次寫了個DOS平臺下的,覺得功能比較弱,也步好用,這次作了個基於MFC的

閒話少說,開始寫代碼吧

1.先進一個基於對話框的MFC應用程序,對話框界面如下圖所示

2.在stdafx.h中加入#include <Afxsock.h>,CApp類的InitInstance()中加入如下代碼

if(!::AfxSocketInit())
 {
  AfxMessageBox("加載動態鏈接庫失敗!");
  return false;
 }

3.在主對話框類中加入一個私有變量SOCKET m_socket,加入一個成員函數

BOOL CComDlg::InitSocket()
{
 m_socket = socket(AF_INET,SOCK_DGRAM,0);
 if(INVALID_SOCKET == m_socket)
 {
  MessageBox("初始化套接字失敗!");
  return false;
 }
 SOCKADDR_IN sockAddr;
 sockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 sockAddr.sin_family = AF_INET;
 sockAddr.sin_port = htons(7000);
    int result;
 result = ::bind(m_socket,(sockaddr*)&sockAddr,sizeof(sockaddr));
 if(SOCKET_ERROR == result)
 {
  MessageBox("綁定套接字失敗!");
  ::closesocket(m_socket);
  return false;
 }
 return true;

}

4.在OnInitDialog()中加入一些代碼,爲了大家看清楚,整個的都拷上了

BOOL CComDlg::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
 InitSocket();
 com *c = new com();
 c->m_hWnd = m_hWnd;
 c->m_socket = m_socket;
    HANDLE hThread = ::CreateThread(NULL,0,Thread,(LPVOID)c,NULL,NULL);
 ::CloseHandle(hThread);
 return TRUE;  // return TRUE  unless you set the focus to a control
}

紅顏色的是加的代碼

5.在RESOURCE.H中定義一個消息#define UM_RECEIVE    WM_USER+1

在對話框類中加入相應的消息響應函數的聲明和實現

聲明:afx_msg void OnReceive(WPARAM wParam,LPARAM lParam);

實現:void CComDlg::OnReceive(WPARAM wParam,LPARAM lParam)
{
 CString strRecv = (char*)lParam;
    CString temp;
 GetDlgItemText(IDC_EDIT_RECV,temp);
 strRecv += "/r/n";
 strRecv += temp;
 SetDlgItemText(IDC_EDIT_RECV,strRecv);
}

6.因爲在OnInitDialog()中創立了一個子線程,所以必須要在對話框類中加入一個靜態的線程處理函數

聲明:static DWORD WINAPI Thread(LPVOID lpParameter);

實現:DWORD WINAPI CComDlg::Thread(LPVOID lpParameter)
{
 SOCKET m_socket = ((com*)lpParameter)->m_socket;
 HWND   m_hWnd   = ((com*)lpParameter)->m_hWnd;
 SOCKADDR_IN sockFrom;
 int len = sizeof(sockaddr);
 char recvBuf[100];
 char tempBuf[100];
 while(true)
 {
  ::recvfrom(m_socket,recvBuf,100,0,(sockaddr*)&sockFrom,&len);
  sprintf(tempBuf,"%s says: %s",inet_ntoa(sockFrom.sin_addr),recvBuf);
  ::PostMessage(m_hWnd,UM_RECEIVE,0,(LPARAM)tempBuf);
 }
 
 return 0;
}

7.添加BUTTOnDWORD WINAPI CComDlg::Thread(LPVOID lpParameter)
{
 SOCKET m_socket = ((com*)lpParameter)->m_socket;
 HWND   m_hWnd   = ((com*)lpParameter)->m_hWnd;
 SOCKADDR_IN sockFrom;
 int len = sizeof(sockaddr);
 char recvBuf[100];
 char tempBuf[100];
 while(true)
 {
  ::recvfrom(m_socket,recvBuf,100,0,(sockaddr*)&sockFrom,&len);
  sprintf(tempBuf,"%s says: %s",inet_ntoa(sockFrom.sin_addr),recvBuf);
  ::PostMessage(m_hWnd,UM_RECEIVE,0,(LPARAM)tempBuf);
 }
 
 return 0;
}

7.添加BUTTON的單擊消息相應函數

void CComDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
    DWORD dwIP;
 CString strSend;
 ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
 GetDlgItemText(IDC_EDIT_SEND,strSend);
    SOCKADDR_IN sockAddr;
 sockAddr.sin_addr.S_un.S_addr = htonl(dwIP);
 sockAddr.sin_family = AF_INET;
 sockAddr.sin_port = htons(7000);
    sendto(m_socket,strSend,strlen(strSend)+1,0,(sockaddr*)&sockAddr,sizeof(sockaddr));
 SetDlgItemText(IDC_EDIT_SEND,"");
}

到這裏,整個的代碼架構終於告一段落了,大家可以做一下,搞清楚了之後,肯定大有收穫啊,

累了,睡了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章