随笔 - 96  文章 - 255  trackbacks - 0
<2010年6月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

E-mail:zbln426@163.com QQ:85132383 长期寻找对战略游戏感兴趣的合作伙伴。

常用链接

留言簿(21)

随笔分类

随笔档案

SDL相关网站

我的个人网页

我的小游戏

资源下载

搜索

  •  

积分与排名

  • 积分 - 484975
  • 排名 - 37

最新评论

阅读排行榜

评论排行榜

之所以把对异常信息的介绍放到原理之前讲,是因为由于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++对于异常)的默认响应方式是终止程序。传统的反应(对于发生异常的时候)则是装糊涂,接着做下去,以期得到最好的结果(《C++程序设计语言》第14章 异常处理)。不过以我目前的水平看来,终止正在进行的程序然后再通过异常机制重新启动一个新的流程,其代价远远大于“装糊涂”的让程序继续运行下去,只要错误不是致命的,通过简单的判断和处理或许效果更佳。
例如,socket中就有一个很有代表性的情况,在TCP连接中,如果一方意外退出——也就是说没有通过TCP退出流程退出,比如没有运行完程序关闭掉socket而直接X掉或者Ctrl+c了。socket往往会因为recv()返回值小于0而抛出一个异常。正常断开连接的时候,recv()会通过返回0表示连接已经断开,但是大多数时候,我们并不希望因为异常的断开就导致另外一端的程序终止(想象一下如果你关掉QQ腾讯的服务器程序就终止是什么概念……),所以我们必须处理这种情况。
在Linux中,远程连接异常断开(被重置)的errno代码是104,类似的,我们应该保证出现这种异常的时候程序可以继续运行。
//Filename: SockClass.hpp

#ifndef SOCK_CLASS_HPP
#define SOCK_CLASS_HPP

#include 
<unistd.h>
#include 
<iostream>
#include 
<sys/socket.h>
#include 
<arpa/inet.h>
#include 
<errno.h>

namespace sockClass
{
void error_info(const char* s);
}
以上是头文件中的声明,下面是函数,我们这里仅仅演示处理了104错误。
namespace sockClass
{
void error_info(const char* s)
{
    
int err_info = errno;
    std::cerr 
<< strerror(err_info) << ": errno: " << err_info << std::endl;
    
if (err_info == 104){
        
return;
    }
    exit(
1);
}
}
在windows中,错误代码由WSAGetLastError()获得,而无需设置errno。
//Filename: SockClass.hpp

#ifndef SOCK_CLASS_HPP
#define SOCK_CLASS_HPP

#include 
<iostream>
#include 
<winsock2.h>

namespace sockClass
{
void error_info(const char* s);
}
WinSock的错误代码跟Linux中的不一样,同样的异常,WinSock的错误代码是10054。
并且,由于没有errno也就无从调用strerror(),我们最好自己写出详细的异常信息。
WinSock的详细代码信息在这里:
http://msdn.microsoft.com/en-us/library/ms740668(v=VS.85).aspx
win32下的演示代码如下:
namespace sockClass
{
void error_info(const char* s)
{
    
int winsock_err = WSAGetLastError();
    perror(s);
    std::cerr 
<< "WinSock Error: " << winsock_err << std::endl;
    
if (winsock_err == WSAECONNRESET) {
        std::cerr 
<< "Connection reset by peer." << std::endl;
        
return;
    }
    exit(
1);
}
}
posted on 2010-06-06 21:07 lf426 阅读(3921) 评论(0)  编辑 收藏 引用 所属分类: SDL入门教程Win32与VCLinux与C++socket 编程入门教程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理