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()会立即返回,并收到多少数据返回多少数据。

  • 相关阅读:
    IE无法打开internet网站已终止操作的解决的方法
    iOS IAP教程
    splice()函数的使用方法
    socket通信简单介绍
    puppet安装和使用
    解惑:NFC手机怎样轻松读取银行卡信息?
    深入浅出谈开窗函数(一)
    TCP/IP协议,HTTP协议
    动态规划0—1背包问题
    栈的链式存储结构及其基本运算的实现
  • 原文地址:https://www.cnblogs.com/lujin49/p/4566281.html
Copyright © 2011-2022 走看看