zoukankan      html  css  js  c++  java
  • 大四中软实习笔记20130306

    1 基于对话框的的TCP服务器建立步骤
    1.1 建立基于对话框的MFC应用程序时,选支持Winsock
    好处:我们不用再写加载/卸载 套接字库,以及头文件和lib文件了

    1.2 设计界面------开启服务的按钮

    1.3 关联 开启服务的成员函数

    1.4 修改OnButtonOpenServer函数
    注意点:
    1 成员变量的使用
    2 在Accept前面使用多线程--------因为是阻塞函数;但需求又必须执行Accept函数


    知识点:
    1 建立多线程
    HANDLE CreateThread(
      LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes   NULL
      DWORD dwStackSize,                         // initial thread stack size         0
      LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread function        新的线程的入口函数
      LPVOID lpParameter,                        // argument for new thread            入口函数的参数---因为是地址,所以可以传进来很多参数
      DWORD dwCreationFlags,                     // creation flags                    0,则新的线程会马上进入 入口函数
      LPDWORD lpThreadId                         // pointer to receive thread ID    NULL,用来存新线程的ID号
    );

    2 入口函数的原型必须和下面一样
    DWORD WINAPI ThreadProc(
      LPVOID lpParameter   // thread data
    );
     
    3 如何退出子线程
        CloseHandle(hThread);//其实不是关闭,而是让子线程的计数器减1。如果不加,相当于子线程永远不会退出,而发生内存泄露。
    注意:它只是让计数器减一

    4 怎样让图标成为 虚的
        GetDlgItem(IDC_BUTTON_OPEN_SERVER)->EnableWindow(FALSE);
        GetDlgItem(IDC_BUTTON_CLOSE_SERVER)->EnableWindow(TRUE);
    注意:    GetDlgItem是成员函数;参数是图标的ID号;返回值是图标对应的对象的地址;
            EnableWindow也是(CWnd)成员函数,它的作用可以让图标变 虚
           
    5 静态成员函数、静态成员变量
    5.1 静态成员函数---外部函数 有相似的地方
    相似:静态成员函数属于1个类,而不属于1个对象    
    所以,静态成员函数的调用有2种方式:
    方式一:跟普通成员函数一样
    方式二:只要在函数名前加 类的作用域就可以
    注意:静态成员函数 只能访问 静态成员变量
    注意:
    在.h中增加static


    5.2 静态成员变量----全局变量 有相似的地方
    相似:静态成员变量属于1个类,而不属于1个对象 
    注意:
    在.h中增加static
    在.cpp中如此使用:
    SOCKET CMfctcpserverDlg::socket_listen=NULL;
    SOCKET CMfctcpserverDlg::socket_connect=NULL;
    而且要放在函数的外面。

    6 自定义消息

    6.1 概念
    BOOL PostMessage(
      HWND hWnd,      // handle of destination window  接收窗口的句柄-------任何窗口都有1个句柄
      UINT Msg,       // message to post                消息名称-----代表1大类消息
      WPARAM wParam,  // first message parameter        消息内容----如buf_recv数组中的数组名
      LPARAM lParam   // second message parameter       
    );
    知识点:
    1 如何得到 主对话框的窗口句柄?
    Dlg类里,天生就有,是基类的成员变量-----m_hWnd

    可以通过CreateThread函数,传给入口函数ThreadProc
    方法:利用如何函数的参数;注意要强制类型转换
    代码如下:

    void CMfctcpserverDlg::OnButtonOpenServer() 
    {
        // TODO: Add your control notification handler code here
    
        socket_listen=socket(AF_INET,SOCK_STREAM,0);
        
        
        struct sockaddr_in addr_b;
        //addr_b.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 
        addr_b.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
        addr_b.sin_port=htons(6588);
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
        
        int flag=listen(socket_listen,4);
        
        
    
        HANDLE hThread=CreateThread(NULL,0,ThreadProc,(LPVOID)m_hWnd,0,NULL);  //此处的m_hWnd是基类的成员变量,就是主对话框的 窗口句柄
        CloseHandle(hThread);//其实不是关闭,而是让子线程的计数器减1。如果不加,相当于子线程永远不会退出,而发生内存泄露。
    
        GetDlgItem(IDC_BUTTON_OPEN_SERVER)->EnableWindow(FALSE);
        GetDlgItem(IDC_BUTTON_CLOSE_SERVER)->EnableWindow(TRUE);    
    }
    
    DWORD WINAPI CMfctcpserverDlg ::ThreadProc(LPVOID lpParameter)
    {
        //SOCKET socket_listen=(SOCKET)lpParameter;        //收到的lpParameter,其实是m_hWnd变量的复制品
        HWND hWnd1=(HWND)lpParameter;                    //通过强制类型转换,恢复了复制品的本来面目,即HWND类型
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
        socket_connect=accept(socket_listen,addr_client,&len);
        
        
        char buf_recv[1000]={'\0'};
        int count=recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        //AfxMessageBox(buf_recv);
        //m_edit_show.Format("%s",buf_recv);
        //UpdateData(FALSE);
        ::PostMessage(m_hWnd1,DATA_USER,(WPARAM)buf_recv,NULL);
    //    WPARAM a;
        
        return 0;
    }

    6.2 改进后的代码

    //声明静态变量
         static SOCKET socket_listen;
         static SOCKET socket_connect;
        static DWORD WINAPI ThreadProc(  LPVOID lpParameter);
    
    //在头文件中添加消息
    afx_msg void OnRecvData(WPARAM wParam, LPARAM lParam);//add
    
    //在cpp中添加函数声明
    ON_MESSAGE(WM_RECV_DATA, OnRecvData) //cpp change
    
    //实现函数体OnRecvData
    void CMfctcpservertest1Dlg::OnRecvData(WPARAM wParam, LPARAM lParam)
    {
        //AfxMessageBox("hello,zhangsan");
        char * recv_str = (char *)wParam;
        int d = strlen(recv_str);
        m_edit_show.Format("%d",d);
        UpdateData(FALSE);
        return;
    }
    
    //修改函数
    DWORD WINAPI CMfctcpservertest1Dlg::ThreadProc(  LPVOID lpParameter)
    {
        HWND hWnd1 = (HWND)lpParameter;
        
        sockaddr_in addr_bb;
        sockaddr * addr_client=(sockaddr *)&addr_bb;
        int len=sizeof(sockaddr);
    
        //SOCKET socket_listen = (SOCKET)lpParameter;
        socket_connect=accept(socket_listen,addr_client,&len);
    
        static char buf_recv[1000]={'\0'};
    
        int count =recv(socket_connect,buf_recv,sizeof(buf_recv)-1,0);
        
        //     m_edit_show.Format("%s",buf_recv);
        //     AfxMessageBox(buf_recv);
        ::PostMessage(hWnd1, WM_RECV_DATA, (WPARAM)buf_recv, NULL);
        //    WPARAM a;
        
        return 0;
    }
    
    void CMfctcpservertest1Dlg::OnButtonOpenserver() 
    {
        // TODO: Add your control notification handler code here
        socket_listen=socket(AF_INET,SOCK_STREAM,0);
            
        struct sockaddr_in addr_b;
        addr_b.sin_addr.S_un.S_addr=htonl(INADDR_ANY); 
        addr_b.sin_port=6588;
        addr_b.sin_family=AF_INET;
        struct sockaddr * addr=(struct sockaddr *)&addr_b;
        bind(socket_listen,addr,sizeof(SOCKADDR));
        
        int flag = listen(socket_listen,4);
    
        HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)m_hWnd, 0, NULL);
        CloseHandle(hThread); //让子线程数目减1,如果不加,可能内存泄漏
        
        GetDlgItem(IDC_BUTTON_OPENSERVER)->EnableWindow(FALSE);
        GetDlgItem(IDC_BUTTON_CLOSESERVER)->EnableWindow(TRUE);
        
    }
    
    void CMfctcpservertest1Dlg::OnButtonCloseserver() 
    {
        // TODO: Add your control notification handler code here
        closesocket(socket_connect);
        closesocket(socket_listen);
    
        GetDlgItem(IDC_BUTTON_OPENSERVER)->EnableWindow(TRUE);
        GetDlgItem(IDC_BUTTON_CLOSESERVER)->EnableWindow(FALSE);
        
    }
  • 相关阅读:
    003random随机数模块
    002---time & datetime
    001---包和模块
    000软件开发规范
    python函数篇
    LeetCode OJ:Construct Binary Tree from Preorder and Inorder Traversal(从前序以及中序遍历结果中构造二叉树)
    LeetCode OJ:Flatten Binary Tree to Linked List(捋平二叉树)
    LeetCode OJ:Convert Sorted Array to Binary Search Tree(将排序好的数组转换成二叉搜索树)
    LeetCode OJ:Count Complete Tree Nodes(完全二叉树的节点数目)
    LeetCode OJ:Validate Binary Search Tree(合法的二叉搜索树)
  • 原文地址:https://www.cnblogs.com/blueswitkey/p/2947460.html
Copyright © 2011-2022 走看看