zoukankan      html  css  js  c++  java
  • C++ 网络编程 总结

    第一次用C++写程序,对C++ 只是菜鸟级别的,倒是对C#很熟悉。两者有很大的相似性。但也有不同。

    首先写了一个网络通讯用的小的MFC程序。发现

    (1)MFC写界面真的好麻烦呀。  用C#写的tab 分分钟搞定的事,用C++害得我写了两天.关键是不熟练. 还有list control 控件的图标显示.  真是很麻烦

             不过,由于最后的 detch() 函数执行后,就真正显示出来了.这些具体的小细节,一般在 书上都没有写.

    (2)用C++ 写类的特征,基本上与C#是相似的.

    说一下网络编程的问题吧

    1一开始并不清楚 C++ 写程序用的网络套接字,三类的不一样的地方.总以为我用的VS2013,用最高级别的套接字应该更容易一些,于是选用了CSOCKET 结果由于这个套接字是阻塞模式,结果被卡住了,卡住不知道如何做了.如果对方设备没有反应,最不能死等吧,这样不行.

    于上网上搜索,发现一篇文章写到 给 CSocket 加上超时.于时照抄照搬着做了一遍,可惜失败了.  怎么查也查不出原因.  按原文章一字一句的比较,也没有找出原因来.失败换思路

    2想到低一点的 CAsyncSocket 是异步操作的.这样总可以了吧不会阻塞了吧.但是回调函数使得处理起来也不方便.在什么时候做处理,就需要消息做处理.但是也很麻烦.

    3于是,找出书来,大部分书上对于网络部分只是介绍了一个最基本的 Socket ,看起来也挺简单的. 就先试一下这个最基本的吧.

    没想到 30分钟后,网络程序测试成功.  而且有超时接收,超时发送,等.正合我意.

    原来最基本的,才是最好的.

    总结一下:

         SOCKET的操作方法

    以下是一个网络客户端的例子:

    // client.cpp  
      
    #include <iostream>  
    #include <cstdio>  
    #include <Winsock2.h>  
      
    using namespace std;  
      
    int main()  
    {  
    // 加载socket动态链接库(dll)  
        WORD wVersionRequested;  
        WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的  
        int err;  
           
        wVersionRequested = MAKEWORD( 1, 1 );   // 请求1.1版本的WinSock库  
           
        err = WSAStartup( wVersionRequested, &wsaData );  
        if ( err != 0 ) {  
            return -1;          // 返回值为零的时候是表示成功申请WSAStartup  
        }  
           
        if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {  
            // 检查这个低字节是不是1,高字节是不是1以确定是否我们所请求的1.1版本  
            // 否则的话,调用WSACleanup()清除信息,结束函数  
            WSACleanup( );  
            return -1;   
        }  
          
    // 创建socket操作,建立流式套接字,返回套接字号sockClient  
        // SOCKET socket(int af, int type, int protocol);  
        // 第一个参数,指定地址簇(TCP/IP只能是AF_INET,也可写成PF_INET)  
        // 第二个,选择套接字的类型(流式套接字),第三个,特定地址家族相关协议(0为自动)  
        SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);  
      
    // 将套接字sockClient与远程主机相连  
        // int connect( SOCKET s,  const struct sockaddr* name,  int namelen);  
        // 第一个参数:需要进行连接操作的套接字  
        // 第二个参数:设定所需要连接的地址信息  
        // 第三个参数:地址的长度  
        SOCKADDR_IN addrSrv;  
        addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");      // 本地回路地址是127.0.0.1;   
        addrSrv.sin_family = AF_INET;  
        addrSrv.sin_port = htons(6000);  
        connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));  
      
        char recvBuf[100];  
        recv(sockClient, recvBuf, 100, 0);  
        printf("%s
    ", recvBuf);  
      
        send(sockClient, "Attention: A Client has enter...
    ", strlen("Attention: A Client has enter...
    ")+1, 0);  
      
        printf("我们可以聊五句话");  
        int n = 5;  
        do{  
            printf("
    还剩%d次:", n);  
            char talk[100];  
            printf("
    Please enter what you want to say next("quit"to exit):");  
            gets(talk);  
            send(sockClient, talk, strlen(talk)+1, 0);          // 发送信息  
      
            char recvBuf[100];  
            recv(sockClient, recvBuf, 100, 0);  
            printf("%s Says: %s
    ", "Server", recvBuf);     // 接收信息  
        }while(--n);  
      
        printf("End linking...
    ");  
        closesocket(sockClient);  
        WSACleanup();   // 终止对套接字库的使用  
      
        printf("
    ");  
        system("pause");  
        return 0;  
    }

    关于超时的处理方法

    在send(),recv()过程中有时由于网络状况等原因,收发不能预期进行,而设置收发超时控制:

    在Linux下需要注意的是时间的控制结构是struct timeval而并不是某一整型数,

    windows下是这样写的:
    int nNetTimeout=1000;//1秒,
    //设置发送超时
    setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
    //设置接收超时
    setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));

    这样做在Linux环境下是不会产生效果的,须如下定义:

    struct timeval timeout = {3,0};
    //设置发送超时
    setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));

    //设置接收超时
    setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

    有两点注意就是:

    1)recv ()的第四个参数需为MSG_WAITALL(设置MSG_DONTWAIT可以不用阻塞在建立连接后在等等接收数据),在阻塞模式下不等到指定数目的数据不会返回,除非超时时间到。还要注意的是只要设置了接收超时,在没有MSG_WAITALL时也是有效的。说到底超时就是不让你的程序老在那儿等,到一定时间进行一次返回而已。

    2)即使等待超时时间值未到,但对方已经关闭了socket, 则此时recv()会立即返回,并收到多少数据返回多少数据。

  • 相关阅读:
    mouse_event模拟鼠标滚轮
    润乾报表配置技术路线
    建筑 物件 开心背单词 读句子,单词,字母,看图例, 翻译,看动画
    文字过渡动画,曲线过渡动画,,使用这个插件assign shape keys
    运动锻炼 开心背单词 读句子,单词,字母,看图例, 翻译,看动画,学英语,轻松背单词,简单背单词
    blender293 内置插件 精度绘画控件,PDT学习003,pdt tangents 切线
    日常用品 背单词 读句子 看图片 读单词 读字母 翻译, 看动画 学英语
    blender293 内置插件 精度绘画控件,PDT学习 precision drawing tools
    乔布斯 背单词 02 读句子 单词 字母 翻译,看动画 学英语 名言 我菜顾我在,我菜故我在,blender加python
    狐狸 和 乌鸦 英语 朗读句子 背单词
  • 原文地址:https://www.cnblogs.com/lujin49/p/4566281.html
Copyright © 2011-2022 走看看