zoukankan      html  css  js  c++  java
  • CSocket服务器(TCP)

    我的理解:把服务器和客户端的交互工程比喻成外来人员访问公司,每来一个客户端访问,需要服务器的前台经理接待此客户,然后前台经理呼叫一个接待员来将客户带上楼。服务器的两个角色前台经理和接待员就是服务器的两个CSocket对象。

    1、需要生成两个类对象,一个用来监听客户的访问,一个用来接待客户。

      在类向导中新建类名:CSockL和CSockC,重写CSockL的OnAccept函数和CSockC的OnReceive和OnClose函数:

      CSockL(1)、

        void CSockL::OnAccept(int nErrorCode)//有客户连接,就回调此函数
        {
        // TODO: 在此添加专用代码和/或调用基类
        CSockC *p=new CSockC;//每有一个访问,就生成一个CSockC对象指针
        this->Accept(*p);
        //p->GetPeerName()可以用来获取刚刚连接的客户端ip和端口
        CSocket::OnAccept(nErrorCode);
        }

      CSockC(2)、

        void CSockC::OnReceive(int nErrorCode)//有客户发送消息,就回调
        {
        // TODO: 在此添加专用代码和/或调用基类
        char rcv[100];//装从客户端传来的数据
        int rcvLenth=Receive(rcv,sizeof(rcv));//核心处
        rcv[rcvLenth]=0;//消除乱码
        CString ipAddrss;//装发送消息的客户端ip地址
        UINT ipPort;//装端口
        int result=GetPeerName(ipAddrss,ipPort);//获取发送消息客户端的ip和端口

        CTestCSoketServerDlg *p=(CTestCSoketServerDlg*)AfxGetMainWnd();//获取主窗口类指针
        p->ShowInfo(rcv,ipAddrss,ipPort);//调用主窗口类指针的显示函数
        CSocket::OnReceive(nErrorCode);
        }

        (3)、

        void SocketS::OnClose(int nErrorCode)//有客户端断开连接回调
        {
        // TODO: 在此添加专用代码和/或调用基类

        CSocket::OnClose(nErrorCode);
        }

    2、现在已经得到一个我自己定义的类CSockL:CSocket,在Dlg.h中声明一个CSockL的对象,在Dlg.cpp中的打开服务器button中定义

      if(!m_sockl.Create(8080))
      {
      AfxMessageBox(CString("创建套接字失败"));
      return;
      }
      m_sockl.Listen();

      注意:服务器不需要指定ip,指定端口创建套接字之后,就可以用于捕获所有本地客户端活动

      所以直接create之后listen就相当于是服务器了。

      另外使用Create之后不能再使用Bind()函数

    3、如果需要从服务器传数据到客户端

      这时所有的客户端都长连接在了服务器上面,在Accept中可以得到这些客户端的ip,所以只要有ip就可以用sendto来发送了。

     笔记:

    客户端套接字使用Send()函数的时候,是将数据放入TCP系统共有的缓冲区,然后TCP系统在服务器将缓冲区的数据接收,使用的是Receive()函数。在服务器接收的过程中,客户端会一直处于阻塞状态,只有当服务器将缓冲区里面的数据全部接收完了之后,客户端才会开始下一次Send()。

    CSocket与线程配合使用:

    发送端:使用AfxBeginThread()生成一个新的线程,在这个线程里面Send()数据就行了。这里应该加入一个确认发送标志,即每发送完一个包之后,就进入一个死循环,当服务器处理了这个包的数据后,向客户端发送一个确认包,客户端解析这个包之后,退出死循环,再进行下一个包的处理。

    接收端:先把数据全部接收到一个buf里面,注意这个buf应尽可能大一点,否则可能会出现粘包的情况。然后通过判断如果是需要的客户端端口发来数据,就进入AfxBeginThread()线程,在这个线程里面处理数据。处理完了之后,想客户端发送确认包,进行下一次的数据处理。

    根据上面的原理,可以实现CSocket+线程传送文件

  • 相关阅读:
    10 个雷人的注释,就怕你不敢用!
    Java 14 之模式匹配,非常赞的一个新特性!
    poj 3661 Running(区间dp)
    LightOJ
    hdu 5540 Secrete Master Plan(水)
    hdu 5584 LCM Walk(数学推导公式,规律)
    hdu 5583 Kingdom of Black and White(模拟,技巧)
    hdu 5578 Friendship of Frog(multiset的应用)
    hdu 5586 Sum(dp+技巧)
    hdu 5585 Numbers
  • 原文地址:https://www.cnblogs.com/judes/p/5902068.html
Copyright © 2011-2022 走看看