C++ mfc版本socket通讯源码分享

来源:互联网 发布:windows store app 编辑:程序博客网 时间:2024/05/17 23:57


这是上个学期网络通讯的课程设计所做的作业,C++语言中的MFC写的。


后面将更新C#版本的基于socket的聊天室程序。废话不多说,直接上源码:








服务端代码:


// sFileDlg.cpp : 实现文件
 //
 #include <winsock2.h>
 #include "stdafx.h"
 #include "sFile.h"
 #include "sFileDlg.h"
 #include "afxdialogex.h"
 #pragma comment(lib, "WS2_32.lib")

 #ifdef _DEBUG
 #define new DEBUG_NEW
 #endif


    UINT server_thd(LPVOID p); //声明线程函数
 SOCKET listen_sock;//定义一个全局的监听soket
 SOCKET sock;//定义一个soket
 CString showeditmsg; //定义全局的显示消息的字符串

 
 
 // CsFileDlg 对话框
 CsFileDlg::CsFileDlg(CWnd* pParent /*=NULL*/)
 : CDialogEx(CsFileDlg::IDD, pParent)
{
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

 void CsFileDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialogEx::DoDataExchange(pDX);
}

 BEGIN_MESSAGE_MAP(CsFileDlg, CDialogEx)
  ON_WM_PAINT()
  ON_WM_QUERYDRAGICON()
  ON_BN_CLICKED(IDC_BtnSend, &CsFileDlg::OnBnClickedBtnsend)
  ON_BN_CLICKED(IDC_BUTTON2, &CsFileDlg::OnBnClickedButton2)
 END_MESSAGE_MAP()


 // CsFileDlg 消息处理程序

 BOOL CsFileDlg::OnInitDialog()
 {
  CDialogEx::OnInitDialog();

  // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
  //  执行此操作
  SetIcon(m_hIcon, TRUE);   // 设置大图标
  SetIcon(m_hIcon, FALSE);  // 设置小图标

  // TODO: 在此添加额外的初始化代码
   show_edit = (CEdit *)GetDlgItem(IDC_EDIT1);
   send_edit = (CEdit *)GetDlgItem(IDC_EDIT2);
   port_edit = (CEdit *)GetDlgItem(IDC_EDIT3);
   star_btn =  (CButton *)GetDlgItem(IDC_BUTTON2);
   showmsg_edit =  (CEdit *)GetDlgItem(IDC_EDIT4);
  return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
 }


 

 // 如果向对话框添加最小化按钮,则需要下面的代码
 //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
 //  这将由框架自动完成。

 void CsFileDlg::OnPaint()
 {
  if (IsIconic())
  {
   CPaintDC dc(this); // 用于绘制的设备上下文

   SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(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
  {
   CDialogEx::OnPaint();
  }
 }

 //当用户拖动最小化窗口时系统调用此函数取得光标
 //显示。
 HCURSOR CsFileDlg::OnQueryDragIcon()
 {
  return static_cast<HCURSOR>(m_hIcon);
 }


 //添加函数update() 更新消息数据
 void CsFileDlg::update(CString s)
 {
  showeditmsg += s;
  show_edit->SetWindowText(showeditmsg);
 }


 //开启服务器按钮响应事件
 void CsFileDlg::OnBnClickedButton2()
 {
  // TODO: 在此添加控件通知处理程序代码
  WSADATA wsData; 
   WSAStartup(MAKEWORD(2,2), &wsData);

   char name[80];
   CString IP;
   CString P;
   hostent* pHost;
   gethostname(name,sizeof(name));//获得主机名
   pHost = gethostbyname(name);//获得主机结构
   IP = inet_ntoa(*(struct in_addr *)pHost->h_addr_list[1]);//获取主机ip地址
   showmsg_edit->SetWindowText("绑定IP地址:" + IP);
   AfxBeginThread(&server_thd,0); //开启新线程处理
 }



 //发送按钮响应事件
 void CsFileDlg::OnBnClickedBtnsend()
 {
   // TODO: 在此添加控件通知处理程序代码
  CString s;
  char * msg;
  send_edit->GetWindowText(s);
  msg = (char*)s.GetBuffer(s.GetLength()); //获取发送的数据的缓冲区的指针

  if(s == "")
   {
        MessageBox("请输入信息");
   }
   else if(send(sock, msg, strlen(msg), 0) == SOCKET_ERROR) //发送数据,并判断是否成功
   {
     update("发送失败\r\n");
   }
   else
   {
     update("我:" + s + "\r\n");//消息上屏
     send_edit->SetWindowText("");//清空输入
     send_edit->SetFocus();//并重获焦点
   }
 }


 
   //添加线程函数server_thd():
   UINT server_thd(LPVOID p)
  {
    WSADATA wsaData;
    WORD wVersion;
    wVersion = MAKEWORD(2,2);
    WSAStartup(wVersion,&wsaData);

    SOCKADDR_IN local_addr;
    SOCKADDR_IN client_addr;
    int iaddrSize = sizeof(SOCKADDR_IN);
    int res;
    char msg[1024];
    CString port;
    CsFileDlg * dlg = (CsFileDlg *)AfxGetApp()->GetMainWnd(); //得到应用程序活动主窗口的指针
    dlg->port_edit->GetWindowText(port);//获得端口地址
    if(port=="")
    {
     AfxMessageBox("请输入端口号");
     return 0;
    }
    //为local_addr赋值,创建soket
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(atoi(port)); //atoi, 把字符串转换成整型数
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
              //创建监听listen_sock
    if( (listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET )
    {
     dlg->update("创建监听失败\r\n");
     return 0;
    }
    //绑定
    if( bind(listen_sock, (struct sockaddr*) &local_addr, sizeof(SOCKADDR_IN)) )
    {
    dlg->update("绑定错误,换一个端口试试吧~\r\n");
    return 0;
    }

    listen(listen_sock, 1); //开始监听,允许最大监听数为1
    dlg->star_btn->EnableWindow(FALSE);  //开启服务器按钮灰化
    dlg->showmsg_edit->ShowWindow(SW_SHOW); //绑定消息edit显示
    dlg->update("已成功开启....\r\n");

    //接受连接请求
    if( (sock = accept(listen_sock, (struct sockaddr *)&client_addr, &iaddrSize)) == INVALID_SOCKET)
    {
    dlg->update("接受连接请求失败\r\n");
    return 0;
    }
    else
    {
     CString port;
     port.Format("%d", int(ntohs(client_addr.sin_port)));
     dlg->update( "已连接来自:" + CString(inet_ntoa(client_addr.sin_addr)) + "  端口:" +
      port+"\r\n");
    }

     ////////////接收数据
    while(1)
    {
 
       if( (res = recv(sock, msg, 1024, 0)) == -1 ) //接收数据,判断是否接收成功
       {
        dlg->update("失去连接\r\n");
        dlg->star_btn->EnableWindow(TRUE);
        break;
       }
       else
       {
        dlg->update("客户端:" + (CString(msg)).Mid(0,res)+"\r\n");
       }
   
    }
     return 0;
   }





  客户端代码:


// cFileDlg.cpp : 实现文件
 //
 #include <winsock2.h>
 #include "stdafx.h"
 #include "cFile.h"
 #include "cFileDlg.h"
 #include "afxdialogex.h"
 #pragma comment(lib, "WS2_32.lib")

 #ifdef _DEBUG
 #define new DEBUG_NEW
 #endif


 SOCKET sock; //创建全局的soket
 UINT recv_thd(LPVOID p); //声明线程函数
 CString edit1msg; // 定义全局的显示消息的字符串


 // CcFileDlg 对话框

 CcFileDlg::CcFileDlg(CWnd* pParent /*=NULL*/)
  : CDialogEx(CcFileDlg::IDD, pParent)
 {
  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 }

 void CcFileDlg::DoDataExchange(CDataExchange* pDX)
 {
  CDialogEx::DoDataExchange(pDX);
 }

 BEGIN_MESSAGE_MAP(CcFileDlg, CDialogEx)
  ON_WM_PAINT()
  ON_WM_QUERYDRAGICON()
  ON_BN_CLICKED(IDC_SEND, &CcFileDlg::OnBnClickedSend)
  ON_BN_CLICKED(IDC_btnConnect, &CcFileDlg::OnBnClickedbtnconnect)
 END_MESSAGE_MAP()


 // CcFileDlg 消息处理程序

 BOOL CcFileDlg::OnInitDialog()
 {
   CDialogEx::OnInitDialog();

   // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
   //  执行此操作
   SetIcon(m_hIcon, TRUE);   // 设置大图标
   SetIcon(m_hIcon, FALSE);  // 设置小图标

   // TODO: 在此添加额外的初始化代码
   //初始化

    edit1 = (CEdit *)GetDlgItem(IDC_EDIT1);
    send_edit = (CEdit *)GetDlgItem(IDC_EDIT2);
    btnconn = (CButton *)GetDlgItem(IDC_btnConnect);
    ip_edit = (CEdit *)GetDlgItem(IDC_EDIT3);
    port_edit = (CEdit *)GetDlgItem(IDC_EDIT4);
    ip_edit->SetWindowText("127.0.0.1");
  return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
 }


 // 如果向对话框添加最小化按钮,则需要下面的代码
 //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
 //  这将由框架自动完成。

 void CcFileDlg::OnPaint()
 {
  if (IsIconic())
  {
   CPaintDC dc(this); // 用于绘制的设备上下文

   SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(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
  {
   CDialogEx::OnPaint();
  }
 }

 //当用户拖动最小化窗口时系统调用此函数取得光标
 //显示。
 HCURSOR CcFileDlg::OnQueryDragIcon()
 {
  return static_cast<HCURSOR>(m_hIcon);
 }




      //更新显示窗口数据
 void CcFileDlg::update(CString s) 
 {
  edit1msg += s;
  edit1->SetWindowText(edit1msg);
 }


     //链接,点连接按钮执行事件
 void CcFileDlg::OnBnClickedbtnconnect()
 {
  // TODO: 在此添加控件通知处理程序代码

  WSADATA wsaData;
  SOCKADDR_IN server_addr;


   WORD wVersion;
   wVersion = MAKEWORD(2,2);
   WSAStartup(wVersion,&wsaData);//使用Socket的程序在使用Socket之前必须调用WSAStartup函数。
   //该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;
   //操作系统利用第二个参数返回请求的Socket的版本信息。
  //当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,
  //然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。
  //该函数执行成功后返回0

   CString ip;
   CString port;
   ip_edit->GetWindowText(ip);//取得服务器的IP地址
   port_edit->GetWindowText(port);//取得服务器的端口

   if(port=="") //判断端口是否为空
   {
    AfxMessageBox("请输入端口号");
    btnconn->EnableWindow(TRUE);
    return;
   }

   //为server_addr赋值 ,创建soket
   server_addr.sin_addr.s_addr = inet_addr((LPCSTR)ip);
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons(atoi(port));

   if( (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) //判断soket是否创建成功
   {
     update("创建Soket错误!\r\n");
     btnconn->EnableWindow(TRUE);
     return;
   }
   if( connect(sock, (struct sockaddr *) &server_addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)//判断链接是否成功
   {
     update("连接失败\r\n");
     btnconn->EnableWindow(TRUE);
     return;
   }
   else
   {
     update("连接成功\r\n");
     AfxBeginThread(&recv_thd, 0); //开启线程处理
     btnconn->EnableWindow(FALSE);//连接按钮变灰
   }
 }


//发送消息按钮处理事件
  void CcFileDlg::OnBnClickedSend()
   {

   CString s;
   char * msg;
   send_edit->GetWindowText(s);
   msg = (char*)s.GetBuffer(s.GetLength()); //获取发送的数据的缓冲区的指针

   if(send(sock, msg, strlen(msg), 0) == SOCKET_ERROR) //判断发送是否成功
   {
     update("发送失败\r\n");
   }
   else if(s == "")   //判断发送的数据是否为空
   {
        MessageBox("请输入信息");
   }
   else
   {
     update("我:"+ s+"\r\n");//消息上屏
     send_edit->SetWindowText("");//清空输入
     send_edit->SetFocus(); //重获焦点
   }
 }


//添加线程函数,接收数据
  UINT recv_thd(LPVOID p)
 {
  int res;
  char msg[1024];
  CString s;
  CcFileDlg * dlg = (CcFileDlg *) AfxGetApp()->GetMainWnd(); //得到应用程序活动主窗口的指针
  dlg->update("开始聊天吧~\r\n");
 
  while(1)
  {
        if( (res = recv(sock, msg, 1024, 0)) == -1) //接收数据,判断是否接收成功
    {
     dlg->update("失去连接~\r\n");
     dlg->btnconn->EnableWindow(TRUE);
     break;
    }
    else
    {
         dlg->update("服务器:" + (CString(msg)).Mid(0,res)+ "\r\n");
    }
  }
  return 0;
 }





                         作者QQ:575674261

            

                         

                        .NET学习交流群 :324087998  (更多实战项目源码分享)




完整代码打包:  http://pan.baidu.com/s/1sj0KarN







1 0
原创粉丝点击