MFC socket 客戶端與伺服器 集合在一起
阿新 • • 發佈:2019-02-10
搞了2天,終於搞定了!效果圖如下
// ServerDlg.cpp : 實現檔案 //robinson_911 作品 #include "stdafx.h" #include "Server.h" #include "ServerDlg.h" #include "afxdialogex.h" #include "ServerSocket.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用於應用程式“關於”選單項的 CAboutDlg 對話方塊 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 對話方塊資料 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支援 // 實現 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CServerDlg 對話方塊 CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CServerDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_str_SendData = _T(""); } void CServerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); // DDX_Control(pDX, IDC_EDIT_IP, m_ServerPort); DDX_Control(pDX, IDC_EDIT_IP, m_ServerIP); DDX_Control(pDX, IDC_EDIT2_Port, m_ServerPort); // DDX_Control(pDX, IDC_LIST1_ReceiveDATA, m_List); DDX_Control(pDX, IDC_LIST2_receivedata, m_List); DDX_Control(pDX, OnConfig, m_Ctrol_connect); DDX_Control(pDX, IDC_COMBO1, m_Select_type); DDX_Control(pDX, IDC_CHECK1, m_ctrlHexSend); // DDX_Control(pDX, IDC_LIST1, m_strSendData); // DDX_Control(pDX, IDC_EDIT2senddata, m_str_SendData); DDX_Text(pDX, IDC_EDIT2senddata, m_str_SendData); } BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(OnConfig, &CServerDlg::OnBnClickedOnconfig) ON_BN_CLICKED(IDC_BUTTON2, &CServerDlg::OnBnClickedButton2) ON_BN_CLICKED(IDCANCEL, &CServerDlg::OnBnClickedCancel) ON_BN_CLICKED(IDC_BUTTON1, &CServerDlg::OnBnClickedButton1) END_MESSAGE_MAP() // CServerDlg 訊息處理程式 BOOL CServerDlg::OnInitDialog() { CDialogEx::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); } } // 設定此對話方塊的圖示。當應用程式主視窗不是對話方塊時,框架將自動 // 執行此操作 m_SockClient.Create(); m_SockClient.SetDialog(this); SetIcon(m_hIcon, TRUE); // 設定大圖示 SetIcon(m_hIcon, FALSE); // 設定小圖示 // TODO: 在此新增額外的初始化程式碼 return TRUE; // 除非將焦點設定到控制元件,否則返回 TRUE } void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向對話方塊新增最小化按鈕,則需要下面的程式碼 // 來繪製該圖示。對於使用文件/檢視模型的 MFC 應用程式, // 這將由框架自動完成。 void CServerDlg::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 CServerDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CServerDlg::OnBnClickedOnconfig()//連線 { // TODO: 在此新增控制元件通知處理程式程式碼 m_bOpenPort=!m_bOpenPort; m_ServerSock.SetDialog(this); CString strPort,strIP; m_ServerPort.GetWindowText(strPort); m_ServerIP.GetWindowText(strIP); int i=m_Select_type.GetCurSel();//server 與client 之間的切換 if(i == 0) //TCP Client { // CClientSocket m_SockClient; if(m_bOpenPort) //關閉連線 { m_Ctrol_connect.SetWindowText("連線"); } else //開啟連線 { CString strStatus; m_Ctrol_connect.SetWindowText("斷開"); if (!strPort.IsEmpty() && !strIP.IsEmpty()) { UINT port = atoi(strPort); if(m_SockClient.Connect(strIP,port)) { MessageBox(_T("Client設定成功!")); } else { MessageBox(_T("Client設定失敗!")); } } } } else if(i == 1) //TCP Server { if(m_bOpenPort) //關閉連線 { m_Ctrol_connect.SetWindowText("連線"); POSITION pos = m_socketlist.GetHeadPosition(); while (pos != NULL) { CClientSocket* socket = (CClientSocket*)m_socketlist.GetNext(pos); if (socket != NULL) delete socket; } m_socketlist.RemoveAll(); // CDialog::OnCancel(); m_ServerSock.Close(); } else //開啟連線 { CString strStatus; m_Ctrol_connect.SetWindowText("斷開"); if (!strPort.IsEmpty() && !strIP.IsEmpty()) { UINT port = atoi(strPort); m_ServerSock.Create(port,SOCK_STREAM,strIP); BOOL ret = m_ServerSock.Listen(); if (ret) MessageBox(_T("Server設定成功!")); } } } } void CServerDlg::ReceiveData(CSocket &socket) { //CString str; TCHAR bufferdata[BUFFERSIZE]; int len = socket.Receive(bufferdata,BUFFERSIZE); if (len != -1) { bufferdata[len] = '\0'; // str= bufferdata; m_List.AddString(bufferdata); /* POSITION pos = m_socketlist.GetHeadPosition(); while (pos != NULL) { CClientSocket* socket = (CClientSocket*)m_socketlist.GetNext(pos); if (socket != NULL) socket->Send(bufferdata,len); }*/ } } void CServerDlg::AcceptConnect() { CClientSocket* psocket = new CClientSocket(); psocket->SetDialog(this); if (m_ServerSock.Accept(*psocket)) m_socketlist.AddTail(psocket); else delete psocket; } void CServerDlg::OnBnClickedButton2()//清除接收區的資料 { // TODO: 在此新增控制元件通知處理程式程式碼 m_List.ResetContent(); UpdateData(FALSE); } void CServerDlg::OnBnClickedCancel() { // TODO: 在此新增控制元件通知處理程式程式碼 CDialogEx::OnCancel(); } void CServerDlg::OnBnClickedButton1()//傳送資料 { // TODO: 在此新增控制元件通知處理程式程式碼 if (socket == NULL) { AfxMessageBox("埠開啟失敗!"); return; } else { UpdateData(TRUE); int i=m_Select_type.GetCurSel();//server 與client 之間的切換 if(i == 0)//client { if(m_ctrlHexSend.GetCheck()) { char data[512]; int len=Str2Hex(m_str_SendData,data); m_SockClient.Send(data,len); } else { m_SockClient.Send(m_str_SendData,(strlen(m_str_SendData)+1)); } } else if(i == 1) //server { if(m_ctrlHexSend.GetCheck()) { char data[512]; int len=Str2Hex(m_str_SendData,data); POSITION pos = m_socketlist.GetHeadPosition(); while (pos != NULL) { CClientSocket* socket = (CClientSocket*)m_socketlist.GetNext(pos); if (socket != NULL) socket->Send(data,len); } } else { POSITION pos = m_socketlist.GetHeadPosition(); while (pos != NULL) { CClientSocket* socket = (CClientSocket*)m_socketlist.GetNext(pos); if (socket != NULL) socket->Send(m_str_SendData,(strlen(m_str_SendData)+1)); } } } } } char CServerDlg::HexChar(char c) { if((c>='0')&&(c<='9')) return c-0x30; else if((c>='A')&&(c<='F')) return c-'A'+10; else if((c>='a')&&(c<='f')) return c-'a'+10; else return 0x10; } //將一個字串作為十六進位制串轉化為一個位元組陣列,位元組間可用空格分隔, //返回轉換後的位元組陣列長度,同時位元組陣列長度自動設定。 int CServerDlg::Str2Hex(CString str, char* data) { int t,t1; int rlen=0,len=str.GetLength(); //data.SetSize(len/2); for(int i=0;i<len;) { char l,h=str[i]; if(h==' ') { i++; continue; } i++; if(i>=len) break; l=str[i]; t=HexChar(h); t1=HexChar(l); if((t==16)||(t1==16)) break; else t=t*16+t1; i++; data[rlen]=(char)t; rlen++; } return rlen; }