• 网编课设


    这个是当时整理的资料,就不整理了。。。。。

    虚拟机IP地址:192.168.109.128

    箭头左边是指针,点左边是 变量;

    VS同时打开多个项目:

    文件-》添加-》现有项目即可;

    可以shift将两个控件选中后,在工具链选中上对齐,右对齐之类的。

    Password控件属性password选为true,以圆点形式出现。

    添加一个对话框,需要添加一个类来找到他。添加完类以后,需要创建窗口,在APPinit里面添加头文件,创建模态窗口。Dlg.domodle();

    assert函数用来不满足条件就终止程序执行!

    Csocket内部模式:(为什么不用创建线程)

    1. 阻塞模式:

    Serve端与客户端处于同步的状态下。在 while循环里不断accept等待客户端的连接,如果在主线程里就会阻塞,需要创建新的线程!

    1. 非阻塞模式:

    基于socket的消息机制,server端与client端的通信处于异步状态,利用 CSocketWnd 作为所有 sockets 的消息池,是实现 socket 事件 的消息机制的关键技术。

     Server socket 正在接收来自 Client socket 连接请求,这将会触发 FD_ACCEPT 事件,同时 Server 端的 网络传输服务进程 向 Server 端的 socket window (CSocketWnd )发送事件通知消息 WM_SOCKET_NOTIFY , 通知有 FD_ACCEPT 事件产生 , CsocketWnd 在收到事件通知消息后,调用消息处理函数 OnSocketNotify:

    项目梳理:

    服务器端:

    1. initinstance里面,加载动态库 ,建立监听socket,,listen,注册页面
    2. Cserversocket 是服务器端监听的socket,重载了onaccept函数,(新建了一个与客户端通信的socket,把这个socket放入队列里;accept函数:第一个是 服务器端与客户端通信的socket的指针,第二个参数是客户端的地址结构体,第三个参数是地质结构体长度的指针,返回的是实际接收到地址的长度。三个参数均为输出型参数!)
    3. CClientsocket是服务器与客户端通信的socket。重载了onreceive函数:根据收到的消息类型,进行不同的处理:

    登录:更新日志,在线列表,通知其他客户端更新列表;

            OnloginIN函数来进行相关处理 :

             更新日志:

               NetcharserverDLGdisplaylog函数更新;

              更新在线列表:

               Updateserver函数:遍历list函数,保存下所有客户端的名字;调用serverDLGupdateuserinfo函数进行更新;

              通知其他客户端更新列表:

                构造一个update的报文(头是那样的,内容为空),fromuser还是那个登录的人,遍历那个list给每一个客户端都发送这个消息;

    发送消息:根据touser进行转发:

    关闭的时候,发送更新报文,更新日志,在线列表;通知其他人更新;

                 更新日志:

                  Ondisplay函数 进行处理;

                更新服务器在线名单:

                 list 中删掉这个节点!调用updateserverlog函数!

                 通知其他客户端更新列表:

                 传给Updateuuser函数所有用户在线名单和from user(为“0”)

    客户端:创建 ,连接,发送,接收!

    1. app文件里的initinstance()函数里添加 动态链接库 ,create套接字(默认分配端口,tcp类型)

    注册登录窗口,

    注册聊天窗口!

    1. loginDLG文件:

       点击登录按钮:

    与服务器 进行连接connect函数;

    发送登录报文;

    Mfc:

    先修改字符集格式:项目->属性->高级->字符集->多字符集

    1.修改窗口大小:在mainframeoncreatewindowcs.cx,cs.cy;

    2.添加菜单:资源视图里menu直接点击添加,写名字。

    dialog里添加资源,画新窗口。添加类。回到menu里,添加事件处理程序,选择在mainframe里,先引入头文件,在函数里面写:cadddlg dlg; dlg.domodal();

    1. intchar数组之间的转换:_itoa_s函数。
    2. 计算器:给button绑定函数:获取编辑框的值,进行运算:

    char ch1[10], ch2[10], ch3[10];

    int num1, num2, num3;

    GetDlgItem(IDC_EDIT1)->GetWindowText(ch1, 10);

    GetDlgItem(IDC_EDIT2)->GetWindowText(ch2, 10);

    num1 = atoi(ch1);

    num2 = atoi(ch2);

    num3 = num1 + num2;

    _itoa_s(num3,ch3,10);

    GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);

    //UpdateData(false);

    也可以给编辑框添加变量:

    UpdateData(true);//是把编辑框中的值传给变量

    result = num1 + num2;

    UpdateData(false);//把变量的值传给编辑框

    QQ聊天程序 :

    服务器端:

    记录谁登陆了,谁离开了;

    转发消息;

    更新在线列表;

    更新日志;

    创建套接字:

    WSAData wsData;

    if(!AfxSocketInit(&wsData))     //加载套接字动态库;

    {

    AfxMessageBox(_T("Socket 库初始化出错!"));

    return false;

    }

    //创建服务器端Socket、采用TCP

    m_iSocket = new CServerSocket();

    if(!m_iSocket)

    {

    AfxMessageBox(_T("动态创建服务器套接字出错!"));

    return false;

    }

    if(!m_iSocket->Create(8989))   //创建套接字,create有三个参数:1.端口号,若为0 或  不   写, 由操作系统随便指定;

                                                                     2.socket—stream类型                      还是 socket_dGram类型,默认是stream类型 ;

    3.IP地址

    自己会调用bind函数进行监听!

    {

    AfxMessageBox(_T("创建套接字错误!"));

    m_iSocket->Close();

    return false;

    }

    if(!m_iSocket->Listen())      //默认最多同时5个来连接 !

    {

    AfxMessageBox(_T("监听失败!"));

    m_iSocket->Close();

    return false;

    }

    功能 一:更新在线列表:

    知识点:Clistbox列表框(对应控件list control

             CListBox* pList = (CListBox*)GetDlgItem(IDC_LT_ONLINE);

              有如下 函数:

    CListBox::ResetContent//清空组合框内容void ResetContent( );

     

    CListBox::AddString//添加lpszString 至组合框尾部int AddString( LPCTSTR lpszString );

     

    CListBox::DeleteString//删除nIndex行int DeleteString( UINT nIndex );

     

    CListBox::InsertString //在nIndex行后,插入行int InsertString( int nIndex, LPCTSTR lpszString );

     

    CListBox::SelectString //可以选中包含指定字符串的行int SelectString( int nStartAfter, LPCTSTR lpszString );

     

    CListBox::FindString //可以在当前所有行中查找指定的字符传的位置,nStartAfter指明从那一行开始进行查找。 int FindString( int nStartAfter, LPCTSTR lpszString ) const;

     

    CListBox::GetCount //获取行数int GetCount( ) const;

     

    CListBox::GetCurSel//获取当前选中行的行号int GetCurSel( ) const;

     

    CListBox::SetCurSel(n)//设置第n行内容为显示的内容int SetCurSel( int nSelect );

    int CListBox::SetItemHeight( int nIndex, UINT cyItemHeight );//设置一个项的高度,注意:列表框具有//LBS_OWNERDRAWVARIABLE风格才可以单独设置一个项的高度,否则是所有项的高度//------------------------上述函数与 CListBox::与CComboBox::::几乎相同

    int CListBox::GetText( int nIndex,CString &rString ) const;//根据索引获得项文本  类似CComboBox::GetLBText

    不知道哪来的struserinfo(遍历保存客户socketlist,用#分割!),他应该包含了所有在线用户的姓名,并用#分割;

    pList->ResetContent();  //清除所有的数据

    while(!strUserInfo.IsEmpty())

    {

    int n = strUserInfo.Find('#');  //查找第一次出现#的位置,读取第一次数据

    strTemp = strUserInfo.Left(n);

    //strArray.Add(strTemp);

    pList->AddString(strTemp);  //加入数据

    strUserInfo = strUserInfo.Right(strUserInfo.GetLength()-n-1); //减去第一个的位置

    }

    服务器接受连接后,把创建的用于和用户数据收发的套接字 保存在一个队列里;用于数据连接的套接字应该是有消息发送过来的时候触发receive函数,收到后,根据头的类型进行不同的操作:

    登录 :更新日志和在线列表,转发给其他用户;

         更新日志:((CEdit*)GetDlgItem(IDC_ET_INFO))->ReplaceSel(strInfo);

    知识点:replacesel函数本来为替换函数,将选中的文本替换为strinfo,但是如果没有选择的文本,就讲strinfo插入现在光标所在的位置!

    发送消息:根据touser转发给相应用户。

    退出:更新日志和在线列表,转发给其他用户.

    更新信息:这种报文一定是由服务器发出的!当客户登录和退出服务器都会发送这样的报文!

    当有一个客户socket要关闭时,会触发onclose函数,在关闭之前要 发送更新信息通知其他客户端和服务器端来更新列表。

    这个客户端的名字是怎么保存进去的?

    服务器端的结构:

    App文件里:

    一个用于监听的socket:m_ISocket


    inITinstance里: 加载socket动态库,create,listen;

                             声明窗口!

    Cserversocket:

                一个用于保存客户端socket的list;

                重写onaccept函数:存进list;

    Cclientsocket :

                重写recevice函数:

                       根据收到的消息:

                                登录:更新服务器的log和 列表,通知客户端更新列表 ;

                                转发:根据to user遍历list转发给相应用户!

                                退出:触发close函数,更新服务器和客户端;

    ServerDlg:  更新在线列表;

    win32:

    #include <Windows.h>
    #include <stdio.h>

    LRESULT CALLBACK WinProc(
        HWND hwnd,      // handle to window
        UINT uMsg,      // message identifier
        WPARAM wParam,  // first message parameter
        LPARAM lParam   // second message parameter
        );

    int WINAPI WinMain(
        HINSTANCE hInstance,      // handle to current instance
        HINSTANCE hPrevInstance,  // handle to previous instance
        LPSTR lpCmdLine,          // command line
        int nCmdShow              // show state
        ){

      WNDCLASS wndcls;
      wndcls.cbClsExtra=0;
      wndcls.cbWndExtra=0;
      wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
      wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
      wndcls.hIcon=LoadIcon(NULL,IDI_QUESTION);
      wndcls.hInstance=hInstance;
      wndcls.lpfnWndProc=WinProc;
      wndcls.lpszClassName="njust";
      wndcls.lpszMenuName=NULL;
      wndcls.style=CS_VREDRAW|CS_HREDRAW;

      RegisterClass(&wndcls);

      HWND hwnd= CreateWindow("njust","test",WS_OVERLAPPEDWINDOW,100,100,300,200,NULL,NULL,hInstance,NULL);

      ShowWindow(hwnd,SW_SHOWNORMAL);
      UpdateWindow(hwnd);

      MSG msg;
      while(GetMessage(&msg,NULL,0,0)){
          TranslateMessage(&msg);
          DispatchMessage(&msg);
      }

       return 0;
    }

    LRESULT CALLBACK WinProc(
        HWND hwnd,      // handle to window
        UINT uMsg,      // message identifier
        WPARAM wParam,  // first message parameter
        LPARAM lParam   // second message parameter
        ){
            switch(uMsg){
            case WM_CLOSE:
                if(IDYES==MessageBox(hwnd,"really exit?","tip",MB_YESNO))
                    PostQuitMessage(0);
                break;

            case WM_CHAR:

                char sChar[50];
                sprintf(sChar,"char is %d",wParam);
                MessageBox(hwnd,sChar,"tip",MB_OK);
                break;

            case WM_LBUTTONDOWN:
                MessageBox(hwnd,"WM_LBUTTONDOWN","tip",MB_OK);

                    break;
            
            default:
                return DefWindowProc(hwnd,uMsg,wParam,lParam);
            }

    }







    #include  <Windows.h>
    //using namespace std;

    LRESULT CALLBACK test(HWND hwnd,      // handle to window
        UINT uMsg,      // message identifier
        WPARAM wParam,  // first message parameter
        LPARAM lParam) // second message parameter);
    {
        return  0;
    }

    //命令行参数和状态
    int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR IpCmdLine, int nCmdShow) {
        //设计
        WNDCLASS   wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.cbWndExtra = 0;
       // wndclass.cbSize = 1000;
        wndclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        wndclass.hCursor = LoadCursor(NULL, IDC_SIZEWE);//instance为什么是null?
        wndclass.hIcon = LoadIcon(NULL, IDI_WARNING);//同上;
        wndclass.hInstance = hinstance;
         wndclass.lpfnWndProc = test;
        wndclass.lpszClassName = "catty";

        wndclass.lpszMenuName = NULL;
        

        //注册窗口类
        RegisterClass(&wndclass);
        //创建
        char* lpClassName = "firstwin32";
        char* lpWindowName = "test";
        HWND hwnd = CreateWindow(lpClassName, lpWindowName, WS_TILEDWINDOW, 0, 0, 500, 500, NULL, NULL, hinstance, NULL);


        //更新显示
        ShowWindow(hwnd, SW_SHOWNORMAL);
        UpdateWindow(hwnd);


  • 相关阅读:
    Springboot中使用Interceptor(拦截器)
    八大排序之冒泡排序
    八大排序之快速排序
    mysql 用户的增删改与授权
    基于Java8开发接口时,处理Java8中的日期
    Springboot中Filter的使用
    正则校验日期,不考虑闰年和闰月
    正则校验时间,24小时制
    记一下mybatis中foreach循环遇到的一个小问题
    sqlserver中一条语句执行查询与更新
  • 原文地址:https://www.cnblogs.com/wtx2333/p/12217444.html
Copyright © 2020-2023  润新知