TCP的客戶端搭建 經過visual studio 驗證 SOCKET編程:搭建一個TCP服務器 visual2017專業版MFC編程環境搭建及第一個MFC程序的建立 MFC開發中添加自定義消息和消息

1、設計目標

  以前已經寫過了TCP服務器原理經過visual studio 驗證 SOCKET編程:搭建一個TCP服務器,這裏咱們搭建一個TCP客戶端界面並對各功能進行實現。設計效果以下:html

2、實驗步驟

2.1客戶端創建

一、工程創建

  新建一個工程,環境有問題的請參考visual2017專業版MFC編程環境搭建及第一個MFC程序的建立編程

 

 

二、控件的添加

  在資源文件——TCPclient.rc服務器

中打開Dialog,雙擊IDD_TCPCLIENT_DIALOG能夠看到對話框異步

刪除掉對話框上原有的控件,添加兩個靜態文本(STATIC),四個編輯框(EDIT)、兩個命令按鈕(BUTTON),佈局以下:socket

三、修改控件屬性

  鼠標選中控件,在屬性對話框中設置其屬性,以下表所示函數

 

修改完成後界面如圖所示:佈局

 

四、爲控件添加相應函數和代碼

 首先,在TCPclientDlg.cpp下的BOOL CTCPclientApp::InitInstance()中添加以下代碼:post

BOOL CTCPclientDlg::OnInitDialog()
{
     CDialogEx::OnInitDialog();
      ...

// TODO: 在此添加額外的初始化代碼
    GetDlgItem(IDC_SENDTEXT)->EnableWindow(false);
    GetDlgItem(IDC_SEND)->EnableWindow(false);
    GetDlgItem(IDC_TEXT)->EnableWindow(false);

	return TRUE;  // 除非將焦點設置到控件,不然返回 TRUE
}

  屏蔽發送消息的功能,避免錯誤的發生。this

而後,對套接字進行初始化,在TCPclientDlg.h中的class CTCPclientDlg : public CDialogEx的public添加定義url

        SOCKET s;
	sockaddr_in addr;        

  在TCPclientDlg.cpp下的BOOL CTCPclientApp::InitInstance()中添加

s = ::socket(AF_INET, SOCK_STREAM, 0);

  完成套接字初始化

  

功能實現,爲鏈接按鈕添加消息響應函數

 

 

 

並編寫事件處理函數以下所示

void CTCPclientDlg::OnConnect()
{
	// TODO: 在此添加控件通知處理程序代碼
	CString str, str1;
	int port;
	GetDlgItem(IDC_ADDR)->GetWindowText(str);
	GetDlgItem(IDC_PORT)->GetWindowText(str1);
	if (str == "" || str1 == "")
	{
		MessageBox("服務器地址或端口不能爲NULL");
	}
	else
	{
		port = atoi(str1.GetBuffer(1));
		addr.sin_family = AF_INET;
		addr.sin_addr.S_un.S_addr = inet_addr(str.GetBuffer(1));
		addr.sin_port = ntohs(port);
		GetDlgItem(IDC_TEXT)->SetWindowText("正在鏈接服務器......\r\n");
		if (::connect(s, (sockaddr*)&addr, sizeof(addr)))
		{
			GetDlgItem(IDC_TEXT)->GetWindowText(str);
			str += "鏈接服務器成功!\r\n";
			GetDlgItem(IDC_TEXT)->SetWindowText(str);
			GetDlgItem(IDC_SENDTEXT)->EnableWindow(true);
			GetDlgItem(IDC_SEND)->EnableWindow(true);
			GetDlgItem(IDC_ADDR)->EnableWindow(false);
			GetDlgItem(IDC_PORT)->EnableWindow(false);
		}
		else
		{
			GetDlgItem(IDC_TEXT)->GetWindowText(str);
			str += "鏈接服務器失敗!請重試\r\n";
			GetDlgItem(IDC_TEXT)->SetWindowText(str);
		}
	}
}

  

當客戶端與服務器鏈接成功以後,用戶便可發送消息到服務器了,爲發送按鈕添加消息訪問函數。

 

void CTCPclientDlg::OnSend()
{
	// TODO: 在此添加控件通知處理程序代碼
		// TODO: Add your control notification handler code here
	CString str, str1;
	GetDlgItem(IDC_SENDTEXT)->GetWindowText(str);
	if (str == "")
	{
		GetDlgItem(IDC_TEXT)->GetWindowText(str1);
		//str1+="\r\n";
		str1 += "消息不能爲空\r\n";
		GetDlgItem(IDC_TEXT)->SetWindowText(str1);
	}
	else
	{
		::send(s, str.GetBuffer(1), sizeof(str), 0);
		GetDlgItem(IDC_TEXT)->GetWindowText(str1);
		str1 += "\r\n";
		str1 += str;
		GetDlgItem(IDC_TEXT)->SetWindowText(str1);
	}
}

  代碼中,經過調用send將消息發送到指定服務器,並將改消息顯示在本地顯示框中,運行結果如圖所示:

 

 做爲客戶端,還應具備接受並顯示服務器所發送消息的功能,,這裏採用異步套接字模式實現該功能。在初始化函數中調用WSAAsyncSelect()函數以下:

	::WSAAsyncSelect(s, this->m_hWnd, WM_SOCKET, FD_READ);

  其中WM_SOCKET定義爲

 #define WM_SOCKET WM_USER+100

  並在class CTCPclientDlg : public CDialogEx的Protect中添加

	afx_msg LRESULT OnSocket(WPARAM wParam, LPARAM lParam);

  添加消息響應函數成功後,還須要在消息映射表中將消息與響應相關聯。在TCPclientDlg.cpp的BEGIN_MESSAGE_MAP中添加代碼以下

	ON_MESSAGE(WM_SOCKET, &CTCPclientDlg::OnSocket)

  

 最後編寫自定義消息響應函數OnSocket(),實現套接字事件處理:

LRESULT CTCPclientDlg::OnSocket(WPARAM wParam, LPARAM lParam)
{
	char cs[100] = { 0 };
	if (lParam == FD_READ)
	{
		CString num = "";
		recv(s, cs, 100, 0);
		GetDlgItem(IDC_TEXT)->GetWindowText(num);
		num += "\r\n服務器說:";
		num += (LPTSTR)cs;
		GetDlgItem(IDC_TEXT)->SetWindowText(num);
	}
	return 0;
}

  因爲本實例,僅處理套接字的讀取事件,因此使用if (lParam == FD_READ)。若是須要處理的套接字事件比較多,,那麼應該在代碼上進行分類判斷。

至此,基本上完成了客戶端應有的功能。在客戶端程序中,須要注意鏈接服務器以前,必定要知道服務器的IP地址等信息,不然,程序將沒法正確鏈接到服務器。

 

 

參考資料

MFC開發中添加自定義消息和消息響應函數

相關文章
相關標籤/搜索