之所以把对异常信息的介绍放到原理之前讲,是因为由于socket本身的复杂性,导致了产生各种异常的复杂性。我们应该时刻铭记的是,sokcet本身属于系统(OS),是系统对TCP/IP的实现,也就是说,socket发出的异常信息不代表程序出错,甚至不代表系统出错,而仅仅就是代表socket本身的各种异常情况。另外一点我觉得应该强调的是:socket不是TCP/IP;TCP/IP也不是socket。socket是为广泛的协议设计的,涉及TCP/IP的内容只是socket体系中一个很小的子集;而TCP/IP就更加独立于sokcet而存在——TCP/IP是协议描述;socket是对协议理论的一种实现形式。

       因为socket是属于系统的,所以不同的系统对于socket有着大同小异的解释,出错描述也不尽相同。在Linux中,socket的异常信息可以通过errno获得(int类型),然后可以通过函数strerror()将int转换成字符串描述;也可以通过函数perror()直接获得其描述。

       要使用errno需要包含头文件<errno.h>。我建议使用errno获得int类的错误信息的一个重要原因在于,socket的异常不一定就必然导致程序终止。Bjarne Stroustrup在介绍C++异常机制的时候对C风格的异常机制有着这样的描述:(C++对于异常)的默认响应方式是终止程序。传统的反应(对于发生异常的时候)则是装糊涂,接着做下去,以期得到最好的结果。不过以我目前的水平看来,终止正在进行的程序然后再通过异常机制重新启动一个新的流程,其代价远远大于“装糊涂”的让程序继续运行下去,只要错误不是致命的,通过简单的判断和处理或许效果更佳。

       例如,socket中就有一个很有代表性的情况,在TCP连接中,如果一方意外退出——也就是说没有通过TCP退出流程退出,比如没有运行完程序关闭掉socket而直接X掉或者Ctrl+c了。socket往往会因为recv()返回值小于0而抛出一个异常。正常断开连接的时候,recv()会通过返回0表示连接已经断开,但是大多数时候,我们并不希望因为异常的断开就导致另外一端的程序终止(想象一下如果你关掉QQ腾讯的服务器程序就终止是什么概念……),所以我们必须处理这种情况。

       在Linux中,远程连接异常断开(被重置)的errno代码是104,类似的,我们应该保证出现这种异常的时候程序可以继续运行。

C++代码
  1. //Filename: SockClass.hpp  
  2.   
  3. #ifndef SOCK_CLASS_HPP  
  4. #define SOCK_CLASS_HPP  
  5.   
  6. #include <unistd.h>  
  7. #include <iostream>  
  8. #include <sys/socket.h>  
  9. #include <arpa/inet.h>  
  10. #include <errno.h>  
  11.   
  12. namespace sockClass  
  13. {  
  14. void error_info(const char* s);  
  15. }  

       以上是头文件中的声明,下面是函数,我们这里仅仅演示处理了104错误。

C++代码
  1. namespace sockClass  
  2. {  
  3. void error_info(const char* s)  
  4. {  
  5.     int err_info = errno;  
  6.     std::cerr << strerror(err_info) << ": errno: " << err_info << std::endl;  
  7.     if (err_info == 104){  
  8.         return;  
  9.     }  
  10.     exit(1);  
  11. }  
  12. }  

       在windows中,错误代码由WSAGetLastError()获得,而无需设置errno。

C++代码
  1. //Filename: SockClass.hpp  
  2.   
  3. #ifndef SOCK_CLASS_HPP  
  4. #define SOCK_CLASS_HPP  
  5.   
  6. #include <iostream>  
  7. #include <winsock2.h>  
  8.   
  9. namespace sockClass  
  10. {  
  11. void error_info(const char* s);  
  12. }  

       WinSock的错误代码跟Linux中的不一样,同样的异常,WinSock的错误代码是10054。

       并且,由于没有errno也就无从调用strerror(),我们最好自己写出详细的异常信息。

       WinSock的详细代码信息在这里:

       http://msdn.microsoft.com/en-us/library/ms740668(v=VS.85).aspx

       Win32下的演示代码如下:

C++代码
  1. namespace sockClass  
  2. {  
  3. void error_info(const char* s)  
  4. {  
  5.     int winsock_err = WSAGetLastError();  
  6.     perror(s);  
  7.     std::cerr << "WinSock Error: " << winsock_err << std::endl;  
  8.     if (winsock_err == WSAECONNRESET) {  
  9.         std::cerr << "Connection reset by peer." << std::endl;  
  10.         return;  
  11.     }  
  12.     exit(1);  
  13. }  
  14. }  
除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.jizhuomi.com/software/423.html
2015年9月8日
作者:鸡啄米 分类:软件开发 浏览: 评论:0