go服务器与mfc做客户端的简单群聊Demo

来源:互联网 发布:韶关市新丰县网络问政 编辑:程序博客网 时间:2024/06/10 09:07

//先前代码对中文处理有问题,以下代码做了修正,

//go语言服务器代码

package mainimport("fmt""net""strconv""runtime" //go线程库    "strings")var conns map[string]net.Conn////////////////////////////////////////////////////////////错误检查//////////////////////////////////////////////////////////func checkError(err error,info string) (res bool) {if(err != nil){fmt.Println(info+"  " + err.Error())//checkOnlineUser()return false}return true}////////////////////////////////////////////////////////////服务器端接收数据线程//参数://数据连接 conn//通讯通道 messages//////////////////////////////////////////////////////////func Handler(conn net.Conn,messages chan string){//fmt.Println("connection is connected from ...",conn.RemoteAddr().String())buf := make([]byte,1024)for{lenght, err := conn.Read(buf)if(checkError(err,"Connection")==false){delete(conns,conn.RemoteAddr().String())conn.Close()checkOnlineUser()break}if lenght > 0{buf[lenght]=0}        fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,buf[:lenght])say := conn.RemoteAddr().String() + " say: ";s := []byte(say)   name := buf[8:lenght]id := buf[4:8]        shead := buf[0:4]        sh := string(shead[:])        sh = strings.Replace(sh, " ", "", -1)  i2,_ := strconv.Atoi(sh)i2 = i2 + len(say)               slen := strconv.Itoa(i2)               sl := fmt.Sprintf("%4s",slen)        head := []byte(sl)content := make([]byte,2048)for i := 0; i < len(head); i++{content[i] = head[i]}j := 0for i:= len(head); i < len(id) + len(head) ; i++{ content[i] = id[j] j++}j=0for i:=len(head)+len(id); i < len(s) + len(head) + len(id) ; i++{content[i] = s[j] j++}j = 0for i:=len(head)+len(id)+len(s); i < len(s) + len(head) + len(id) + len(name); i++{content[i] = name[j] j++}    sum := len(s) + len(head) + len(id) + len(name)reciveStr := string(content[:sum])       messages <- reciveStr}}//////////////////////////检测在线用户////////////////////////func checkOnlineUser(){       var msg string    var slen string      //for{    for key,_ := range conns {//fmt.Println("connection is connected from ...",key)msg += key;     msg += "-";}    l1:=len([]rune(msg))     if l1==0{    return    }msg = string(msg[0:l1-1])        slen = strconv.Itoa(l1-1)         //fmt.Println(slen)        sl := fmt.Sprintf("%4s",slen)       // fmt.Println(sl)        stype := "1000"        msg = sl + stype + msgfor _,value := range conns {//fmt.Println("发送内容",msg) runtime.Gosched();_,err :=value.Write([]byte(msg)) if(err != nil){fmt.Println(err.Error(),"checkOnlineUser")//delete(conns,key)}else{fmt.Println("发送用户列表了")}}    // }}////////////////////////////////////////////////////////////服务器发送数据的线程////参数//连接字典 conns//数据通道 messages//////////////////////////////////////////////////////////func echoHandler(conns *map[string]net.Conn,messages chan string){for{msg:= <- messagesfor _,value := range *conns {//fmt.Println("connection is connected from ...",key)_,err :=value.Write([]byte(msg))if(err != nil){fmt.Println(err.Error(),"123")//delete(*conns,key)}}}}////////////////////////////////////////////////////////////启动服务器//参数//端口 port//////////////////////////////////////////////////////////func StartServer(port string){service:=":"+port //strconv.Itoa(port);tcpAddr, err := net.ResolveTCPAddr("tcp4", service)checkError(err,"ResolveTCPAddr")l,err := net.ListenTCP("tcp",tcpAddr)checkError(err,"ListenTCP")//conns=make(map[string]net.Conn)messages := make(chan string)//imsgstart = 1//启动服务器广播线程go echoHandler(&conns,messages)for  {fmt.Println("msg  Listening ...")conn,err := l.Accept()checkError(err,"Accept")fmt.Println("Accepting ...")conns[conn.RemoteAddr().String()]=conn//fmt.Println(conn.RemoteAddr().String()) checkOnlineUser()//启动一个新线程go Handler(conn,messages) }}func main(){    conns=make(map[string]net.Conn)   go StartServer("7777");fmt.Println("服务启动完成")for{}}


//mfc客户端主要代码
// qunliaoDlg.cpp : 实现文件//#include "stdafx.h"#include "qunliao.h"#include "qunliaoDlg.h"#include <atlbase.h>#include <boost/format.hpp>     #include <boost/tokenizer.hpp>     #include <boost/algorithm/string.hpp>   #include < boost/locale/encoding.hpp>#include <boost/date_time/posix_time/posix_time.hpp>   #define BOOST_DATE_TIME_SOURCE   #ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialog{public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)END_MESSAGE_MAP()// CqunliaoDlg 对话框CqunliaoDlg::CqunliaoDlg(CWnd* pParent /*=NULL*/): CDialog(CqunliaoDlg::IDD, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CqunliaoDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);DDX_Control(pDX, IDC_LIST3, m_ListCtrl);DDX_Control(pDX, IDC_EDIT2, m_EditSendText);DDX_Control(pDX, IDC_LIST1, m_ListMsg);}BEGIN_MESSAGE_MAP(CqunliaoDlg, CDialog)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()//}}AFX_MSG_MAPON_BN_CLICKED(IDC_BUTTON1, &CqunliaoDlg::OnBnClickedButton1)ON_WM_CLOSE()ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST3, &CqunliaoDlg::OnNMCustomdrawList3)ON_BN_CLICKED(IDC_BUTTON2, &CqunliaoDlg::OnBnClickedButton2)END_MESSAGE_MAP()void CqunliaoDlg::init(){      tcp::resolver resolver(io_service);    tcp::resolver::query query("127.0.0.1", "7777");    tcp::resolver::iterator iterator = resolver.resolve(query);tcp::resolver resolver2(io_service_user);    tcp::resolver::query query2("127.0.0.1", "8888");    tcp::resolver::iterator iterator2 = resolver2.resolve(query2);buser = true;bmsg = true;m_pclient = boost::shared_ptr<chat_client>(new chat_client(io_service, iterator));//m_puserclient = boost::shared_ptr<chat_client_user>(new chat_client_user(io_service, iterator2));//m_pusername = boost::shared_ptr<chat_client>(new chat_client(io_service, iterator));m_pthread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service)));//m_pthread2 = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_user)));m_pmsgthread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CqunliaoDlg::GetMessage,this)));//m_puserthread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CqunliaoDlg::GetUserList,this)));//m_pusernamethread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CqunliaoDlg::GetUserName,this)));//m_pthread->detach();//m_pmsgthread->detach();}// CqunliaoDlg 消息处理程序BOOL CqunliaoDlg::OnInitDialog(){CDialog::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码m_ListMsg.DeleteAllItems();m_ListMsg.InsertColumn(0, _T(""));    m_ListMsg.SetColumnWidth(0, 200);//设置列宽  m_ListCtrl.DeleteAllItems();m_ListCtrl.InsertColumn(0, _T(""));    m_ListCtrl.SetColumnWidth(0, 160);//设置列宽      init();return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CqunliaoDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CqunliaoDlg::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{CDialog::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CqunliaoDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}//void CqunliaoDlg::GetUserName()//{//while(true){//if(m_puserclient->GetChatMessage().body_length()){//m_strUserName =  m_puserclient->GetChatMessage().body();//m_puserclient->GetChatMessage().clear();//break;//}else{//   boost::this_thread::sleep(boost::posix_time::seconds(1));  //}//}//m_puserthread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CqunliaoDlg::GetUserList,this)));//}void CqunliaoDlg::GetUserMsg(){        std::string strTime = boost::posix_time::to_iso_string(              boost::posix_time::second_clock::local_time());                // 这时候strTime里存放时间的格式是YYYYMMDDTHHMMSS,日期和时间用大写字母T隔开了                 int pos = strTime.find('T');              strTime.replace(pos,1,std::string(" "));              strTime.replace(pos + 3,0,std::string(":"));              strTime.replace(pos + 6,0,std::string(":"));  strTime.replace(0+4,0,std::string("-"));strTime.replace(0+4+3,0,std::string("-"));//std::string str2();std::wstring wStr = boost::locale::conv::utf_to_utf<wchar_t>( m_pclient->GetChatMessage().body() );CString str(wStr.c_str());CString strtime(strTime.c_str());int i = m_ListMsg.GetItemCount();CString col;col.Format(_T("%d"),i);m_ListMsg.InsertItem(i,col);m_ListMsg.SetItemText(i,0,strtime);col.Format(_T("%d"),i+1);m_ListMsg.InsertItem(i+1,col);//str = m_strUserName + "说:" + str;m_ListMsg.SetItemText(i+1,0,str);m_pclient->GetChatMessage().clear();}void CqunliaoDlg::GetUserList(){  {//CString str();    std::vector<std::string> vecSegTag;                // boost::is_any_of这里相当于分割规则了     std::string str = m_pclient->GetChatMessage().body();            boost::split(vecSegTag, str ,boost::is_any_of(_T("-")));  m_ListCtrl.DeleteAllItems();CString col, strname;//std::string tmp;for(int i = 0; i < vecSegTag.size(); i++){       col.Format(_T("%d"),i);     m_ListCtrl.InsertItem(i,col); CString strname(vecSegTag[i].c_str()); m_ListCtrl.SetItemText(i,0,strname);}/*int i = m_ListCtrl.GetItemCount();CString col;col.Format(_T("%d"),i);m_ListCtrl.InsertItem(i,col);m_ListCtrl.SetItemText(i,0,str);*/m_pclient->GetChatMessage().clear();}}void CqunliaoDlg::GetMessage(){while(bmsg){try{if(m_pclient->GetChatMessage().body_length()){std::string msgtype = m_pclient->GetChatMessage().type();if(msgtype=="1000")//用户列表{GetUserList();}else{   GetUserMsg();}}else{   boost::this_thread::sleep(boost::posix_time::seconds(1));  }}catch(std::exception e){return;}catch(...){return;}}}void CqunliaoDlg::OnBnClickedButton1(){// TODO: 在此添加控件通知处理程序代码  using namespace std; // For strlen and memcpy.  USES_CONVERSION;      chat_message msg;  CString str;  m_EditSendText.GetWindowText(str);  if(str.IsEmpty()) {     return;  } // char *chr=T2A(str);  //char *chr = "我";  std::wstring wstr = str.GetString();  string test2=boost::locale::conv::from_utf(wstr,"UTF-8");      //WideCharToMultiByte(CP_ACP,0,str.GetBuffer(),-1,chr,str.GetLength(),NULL,NULL);  msg.body_length(test2.length());  memcpy(msg.body(), test2.c_str(), msg.body_length());      msg.encode_header();  msg.msg_type("1001");      m_pclient->write(msg);  //delete chr; // chr = NULL;}void CqunliaoDlg::OnClose(){// TODO: 在此添加消息处理程序代码和/或调用默认值m_pthread->interrupt();//m_pthread2->interrupt();m_pclient->close();//m_puserclient->close();//m_pthread->join();buser=false;bmsg=false;    m_pmsgthread->join();  //  m_puserthread->join();    //m_pthread->interrupt();m_pmsgthread->interrupt();//m_puserthread->interrupt();CDialog::OnClose();}void CqunliaoDlg::OnNMCustomdrawList3(NMHDR *pNMHDR, LRESULT *pResult){LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);// TODO: 在此添加控件通知处理程序代码*pResult = 0;}


boost的asio代码

//// chat_client.hpp// ~~~~~~~~~~~~~~~//// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)//// Distributed under the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//#include <cstdlib>#include <deque>#include <iostream>#include <boost/array.hpp>#include <boost/bind.hpp>#include <boost/asio.hpp>#include <boost/thread.hpp>#include <boost/shared_ptr.hpp>  #include "chat_message.hpp"using namespace boost::asio;using boost::asio::ip::tcp;typedef std::deque<chat_message> chat_message_queue;class chat_client{public:  chat_client(boost::asio::io_service& io_service,      tcp::resolver::iterator endpoint_iterator)    : io_service_(io_service),      socket_(io_service)  {data_.assign('\0');    //tcp::endpoint endpoint = *endpoint_iterator;tcp::endpoint endpoint(ip::address_v4::from_string("127.0.0.1"), 7777);    socket_.async_connect(endpoint,        boost::bind(&chat_client::handle_connect, this,          boost::asio::placeholders::error, ++endpoint_iterator));  }  void write(const chat_message& msg)  {    io_service_.post(boost::bind(&chat_client::do_write, this, msg));  }  //void write(const std::string& user){  //  io_service_.post(boost::bind(&chat_client::do_write, this, user));  //}  void close()  {    io_service_.post(boost::bind(&chat_client::do_close, this));  }  public:  chat_message& GetChatMessage(){    return read_msg_;  }private:  void handle_connect(const boost::system::error_code& error,      tcp::resolver::iterator endpoint_iterator)  {    if (!error)    {      boost::asio::async_read(socket_,          boost::asio::buffer(read_msg_.data(), chat_message::header_length),          boost::bind(&chat_client::handle_read_header, this,            boost::asio::placeholders::error));    }    /*else if (endpoint_iterator != tcp::resolver::iterator())    {      socket_.close();      tcp::endpoint endpoint = *endpoint_iterator;      socket_.async_connect(endpoint,          boost::bind(&chat_client::handle_connect, this,            boost::asio::placeholders::error, ++endpoint_iterator));    }*/  }  void handle_read_header(const boost::system::error_code& error)  { /* if(!error &&strcmp(read_msg_.data(),"user")==0){ boost::asio::async_read(socket_, boost::asio::buffer(read_msg_.user(), 1024),          boost::bind(&chat_client::handle_read_userlist, this,            boost::asio::placeholders::error));  }    else */if (!error && read_msg_.decode_header())    {      boost::asio::async_read(socket_,          boost::asio::buffer(read_msg_.msg_type(), chat_message::msg_type_length),          boost::bind(&chat_client::handle_read_msg_type, this,            boost::asio::placeholders::error));    }    else    {      do_close();    }  }   void handle_read_msg_type(const boost::system::error_code& error)  {    if (!error)    {std::cout.write(read_msg_.msg_type(), chat_message::msg_type_length);      std::cout << "\n";      boost::asio::async_read(socket_,  boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),          boost::bind(&chat_client::handle_read_body, this,            boost::asio::placeholders::error));    }    else    {      do_close();    }  }  void handle_read_body(const boost::system::error_code& error)  {    if (!error)    {      std::cout.write(read_msg_.body(), read_msg_.body_length());      std::cout << "\n";      boost::asio::async_read(socket_,          boost::asio::buffer(read_msg_.data(), chat_message::header_length),          boost::bind(&chat_client::handle_read_header, this,            boost::asio::placeholders::error));    }    else    {      do_close();    }  }  void handle_read_userlist(const boost::system::error_code& error)  {    if (!error)    {      /*std::cout.write(read_msg_.body(), read_msg_.body_length());      std::cout << "\n";*/  m_userlist.append(data_.data());  data_.assign('\0');      boost::asio::async_read(socket_,          boost::asio::buffer(data_),          boost::bind(&chat_client::handle_read_userlist, this,            boost::asio::placeholders::error));    }    else    {      do_close();    }  }  void do_write(chat_message msg)  {    bool write_in_progress = !write_msgs_.empty();    write_msgs_.push_back(msg);    if (!write_in_progress)    {      boost::asio::async_write(socket_,          boost::asio::buffer(write_msgs_.front().data(),            write_msgs_.front().length()),          boost::bind(&chat_client::handle_write, this,            boost::asio::placeholders::error));    }  }  //void do_write(std::string& user)  //{  //   //  {  //    boost::asio::async_write(socket_,  //        boost::asio::buffer(user,  //          user.length()),  //        boost::bind(&chat_client::handle_write, this,  //          boost::asio::placeholders::error));  //  }  //}  void handle_write(const boost::system::error_code& error)  {    if (!error)    {      write_msgs_.pop_front();      if (!write_msgs_.empty())      {        boost::asio::async_write(socket_,            boost::asio::buffer(write_msgs_.front().data(),              write_msgs_.front().length()),            boost::bind(&chat_client::handle_write, this,              boost::asio::placeholders::error));      }    }    else    {      do_close();    }  }  void do_close()  {    socket_.close();  }private:  boost::asio::io_service& io_service_;  tcp::socket socket_;  chat_message read_msg_;  chat_message_queue write_msgs_;  std::string m_userlist;  boost::array<char, 1024> data_;};//int main(int argc, char* argv[])//{//  try//  {//  /*  if (argc != 3)//    {//      std::cerr << "Usage: chat_client <host> <port>\n";//      return 1;//    }*/////    boost::asio::io_service io_service;//   // boost::asio::ip::tcp::socket socket(io_service); //std::string ip = boost::asio::ip::address().to_string();//    tcp::resolver resolver(io_service);//    tcp::resolver::query query("127.0.0.1", "7777");//    tcp::resolver::iterator iterator = resolver.resolve(query);//////tcp::resolver::iterator end; // End marker.  // //   while (iterator != end)  // //   {  // //       tcp::endpoint ep = *iterator++;  // //       std::cout << ep.address().to_string() << std::endl;  ////std::cout << ep.port() << std::endl;// //   }  //   // getchar();//    chat_client c(io_service, iterator);////    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));////    char line[chat_message::max_body_length + 1];//    while (std::cin.getline(line, chat_message::max_body_length + 1))//    {//      using namespace std; // For strlen and memcpy.//      chat_message msg;//      msg.body_length(strlen(line));//      memcpy(msg.body(), line, msg.body_length());//      msg.encode_header();//      c.write(msg);//    }////    c.close();//    t.join(); //  }//  catch (std::exception& e)//  {//    std::cerr << "Exception: " << e.what() << "\n";//  }////  return 0;//}

//
// chat_message.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//


#ifndef CHAT_MESSAGE_HPP
#define CHAT_MESSAGE_HPP


#include <cstdio>
#include <cstdlib>
#include <cstring>


class chat_message
{
public:
  enum { header_length = 4 };
  enum { max_body_length = 2048 };
  enum { msg_type_length = 4 };


  chat_message()
    : body_length_(0)
  {
 memset(data_,0,header_length + msg_type_length + max_body_length);
 memset(msg_type_,0,msg_type_length+1);
  }


  const char* data() const
  {
    return data_;
  }


  char* data()
  {
    return data_;
  }


  void clear()
  {
     memset(data_,0,header_length + msg_type_length + max_body_length);
memset(msg_type_,0,msg_type_length+1);
     body_length_ = 0;
  }


  size_t length() const
  {
    return header_length + msg_type_length + body_length_;
  }


  const char* body() const
  {
    return data_ + header_length + msg_type_length ;
  }


  char * msg_type(){
  
 return data_ + header_length;
  }
  const char* type(){


      strncat(msg_type_, data_+header_length,msg_type_length );
 return msg_type_;
  }
  char* body()
  {
    return data_ + header_length+ msg_type_length ;
  }
  char* user(){
     return data_ + header_length+ msg_type_length ;
  }
  size_t body_length() const
  {
    return body_length_;
  }


  void body_length(size_t length)
  {
    body_length_ = length;
    if (body_length_ > max_body_length)
      body_length_ = max_body_length;
  }


  bool decode_header()
  {
    using namespace std; // For strncat and atoi.
    char header[header_length + 1] = "";
    strncat(header, data_, header_length);
    body_length_ = atoi(header);
    if (body_length_ > max_body_length)
    {
      body_length_ = 0;
      return false;
    }
    return true;
  }


  void msg_type(std::string stype)
  {
 memcpy(data_+header_length,stype.c_str(), msg_type_length);
  }


  void encode_header()
  {
    using namespace std; // For sprintf and memcpy.
    char header[header_length + 1] = "";
    sprintf(header, "%4d", body_length_);
    memcpy(data_, header, header_length);
  }


private:
  char data_[header_length + msg_type_length + max_body_length];
  char msg_type_[msg_type_length+1];
  size_t body_length_;
};


#endif // CHAT_MESSAGE_HPP

0 0
原创粉丝点击