zoukankan      html  css  js  c++  java
  • TCP的客户端搭建

    一、设计目标

      之前已经写过了TCP服务器原理通过visual studio 验证 SOCKET编程:搭建一个TCP服务器,这里我们搭建一个TCP客户端界面并对各功能进行实现。设计效果如下:

    二、实验步骤

    2.1客户端建立

    1、工程建立

      新建一个工程,环境有问题的请参考visual2017专业版MFC编程环境搭建及第一个MFC程序的创建

    2、控件的添加

      在资源文件——TCPclient.rc

    中打开Dialog,双击IDD_TCPCLIENT_DIALOG可以看到对话框

    删除掉对话框上原有的控件,添加两个静态文本(STATIC),四个编辑框(EDIT)、两个命令按钮(BUTTON),布局如下:

    3、修改控件属性

      鼠标选中控件,在属性对话框中设置其属性,如下表所示

    修改完成后界面如图所示:

    4、为控件添加相应函数和代码

     首先,在TCPclientDlg.cpp下的BOOL CTCPclientApp::InitInstance()中添加如下代码:

    BOOL CTCPclientDlg::OnInitDialog()
    {
         CDialogEx::OnInitDialog();
          ...
    
    // TODO: 在此添加额外的初始化代码
        GetDlgItem(IDC_SENDTEXT)->EnableWindow(false);
        GetDlgItem(IDC_SEND)->EnableWindow(false);
        GetDlgItem(IDC_TEXT)->EnableWindow(false);
    
    	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }
    

      屏蔽发送消息的功能,避免错误的发生。

    然后,对套接字进行初始化,在TCPclientDlg.h中的class CTCPclientDlg : public CDialogEx的public添加定义

            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("正在连接服务器......
    ");
    		if (::connect(s, (sockaddr*)&addr, sizeof(addr)))
    		{
    			GetDlgItem(IDC_TEXT)->GetWindowText(str);
    			str += "连接服务器成功!
    ";
    			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 += "连接服务器失败!请重试
    ";
    			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+="
    ";
    		str1 += "消息不能为空
    ";
    		GetDlgItem(IDC_TEXT)->SetWindowText(str1);
    	}
    	else
    	{
    		::send(s, str.GetBuffer(1), sizeof(str), 0);
    		GetDlgItem(IDC_TEXT)->GetWindowText(str1);
    		str1 += "
    ";
    		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 += "
    服务器说:";
    		num += (LPTSTR)cs;
    		GetDlgItem(IDC_TEXT)->SetWindowText(num);
    	}
    	return 0;
    }
    

      由于本实例,仅处理套接字的读取事件,所以使用if (lParam == FD_READ)。如果需要处理的套接字事件比较多,,那么应该在代码上进行分类判断。

    至此,基本上完成了客户端应有的功能。在客户端程序中,需要注意连接服务器之前,一定要知道服务器的IP地址等信息,否则,程序将无法正确连接到服务器。

    参考资料

    MFC开发中添加自定义消息和消息响应函数

  • 相关阅读:
    编程题--简易消除
    条件随机场理论分析CRF(Conditional Random Field)
    受限玻尔兹曼机和深度置信网络
    深度学习的起源、发展和现状
    条件随机场matlab程序下载
    Matlab 运行C程序出现的编译出错问题
    python爬取安居客二手房网站数据
    小白开始
    prctl系统调用设置进程名
    Java 中的 super 关键字
  • 原文地址:https://www.cnblogs.com/noticeable/p/10419103.html
Copyright © 2011-2022 走看看