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{}}
// 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
- go服务器与mfc做客户端的简单群聊Demo
- MFC Socket简单服务器与客户端源码
- MFC Socket简单服务器与客户端源码
- SpringMVC 做服务器,httpClient做客户端请求的简单例子
- 基于TCP的服务器和客户端的简单收发Demo
- 基于TCPClient的客户端服务器的简单通信demo
- VLC做RTSP服务器,自己写客户端与服务器命令交互demo
- Socket+NIO实现客户端与服务器的通信的Demo
- TCP客户端与服务器MFC
- 简单的python流回显服务器与客户端
- 简单的TCP服务器与客户端
- 简单的TCP服务器与客户端通讯
- 使用nc和go做简易测速服务器和客户端
- MFC实现与手机客户端通信的http服务器
- MFC网络编程TCP/IP的服务器与客户端代码
- Android TCP 文件客户端与服务器DEMO
- Android TCP 文件客户端与服务器DEMO
- Android TCP 文件客户端与服务器DEMO
- 在构造函数/析构函数中调用虚函数
- 搭建自己的腾讯云服务器
- .net 中句柄的理解
- 入门训练 圆的面积
- c# 变量空值&设置空值默认值
- go服务器与mfc做客户端的简单群聊Demo
- theano,cuda,cudnn,cnmen
- mipmap 目录和drawable 目录有什么区别
- 类 - 复制构造函数
- 千视通AI技术助力黔西南州公安大数据防控体系建设
- 人工智能在深度学习领域的前世今生
- Android 系列 4.7发送/接收广播消息
- Git Subtree 的使用
- java判断字符串中某字符出现的位置,并替换指定指定内容