网编课设

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

虚拟机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);


猜你喜欢

转载自www.cnblogs.com/wtx2333/p/12217444.html