春季总结(四)

本文详细介绍了软件开发的六个阶段,从需求分析到部署实施,强调了软件设计师在设计阶段的角色。同时,讨论了IPv6在连接支持中的应用,展示了如何在代码中同时处理IPv4和IPv6。此外,解释了C++与C在函数重载、默认参数和内存管理上的差异。最后,阐述了单例模式和静态成员函数的概念及其用途。
摘要由CSDN通过智能技术生成

目录

1、软件设计师

2、ipv6

3、C C++的区别

4、设计模式详细

5、静态成员函数


1、软件设计师

项目经理》软件架构师》软件设计师》程序员

第一阶段:假想阶段 产品经理

本阶段是整个软件开发的开始阶段,输入可以是为了提高工作效率的某个好的想法或者是公司领导为了帮助管理发出的命令。输出就是业务需求文档,英文称为Business Requirement Document。

第二阶段:需求开发阶段 软件架构师

本阶段的主要工作是基于业务需求文档进一步分析业务人员的真实需求,输入是假想阶段的业务需求文档,输出是功能说明文档,英文称为Funtion Specification。所以本阶段需要很多重要角色的参与,之前提到过的有软件产品设计师,软件开发架构师,软件开发负责人,软件测试负责人和业务负责人。这些角色要共同齐心合力完成一份高质量的功能说明文档。

第三阶段:设计阶段  软件设计师

本阶段的输入是功能说明文档,输出是软件架构设计文档,硬件架构设计文档,测试计划文档。硬件设计可以分为概要设计和详细设计,概要设计通常要描述出有几个环境,每个环境有几台服务器,使用的是虚拟服务器还是物理服务器,每个服务器的作用,分别在哪个级别的安全区域,防火墙分布,负载均衡设备的分布,数据库产品信息,是单实例还是集群;详细设计除了要描述出这些信息还要描述出每台服务器的硬件配置信息,地址,开放的端口,HTTP请求或者其他类型的请求的走向,软件设计可以分为概要设计和详细设计,概要设计通常要描述出有几个主要组成部分,每个部分的存在形式和功能。实现技术部分要把所有用到的运行时环境,编程语言,第三方类库描述清楚。

第四阶段:实现阶段  程序员

如果设计阶段的工作做得足够充分,那么这个阶段的工作将变得容易得多。这个阶段的输入是设计文档。输出是源代码和构建出来的软件安装包。源代码的书写必须遵循统一的规范,必须遵循设计阶段定义的统一的架构,必须达到规定的安全标准,用合理的方式实现设计文档所设计的功能。

第五阶段:质量检查阶段

这个阶段的输入是准备测试的系统和测试案例。输出是缺陷记录和缺陷报告。

第六阶段:部署阶段

这个阶段的输入是可供部署的软件安装包和部署文档。输出是可供用户使用的业务系统,备份和恢复计划。

总结:

我们可以这样看待一个业务软件,对于一个业务软件有业务线,软件线,硬件线三条线,业务想法由软件来实现,软件需要运行在硬件上。

截止UML2.0一共有13种图形(UML1.5定义了9种,2.0增加了4种)。分别是:用例图、类图、对象图、状态图、活动图、顺序图、协作图、构件图、部署图9种,包图、组合结构图、交互概览图3种。 [1] 

  • 用例图:从用户角度描述系统功能。

  • 类图:描述系统中类的静态结构。

  • 对象图:系统中的多个对象在某一时刻的状态。

  • 状态图:是描述状态到状态控制流,常用于动态特性建模

  • 活动图:描述了业务实现用例的工作流程

  • 顺序图:对象之间的动态合作关系,强调对象发送消息的顺序,同时显示对象之间的交互

  • 协作图:描述对象之间的协助关系

  • 构件图:一种特殊的UML图来描述系统的静态实现视图

  • 部署图:定义系统中软硬件的物理体系结构

  • 包图:对构成系统的模型元素进行分组整理的图

  • 组合结构图:表示类或者构建内部结构的图

  • 交互概览图:用活动图来表示多个交互之间的控制关系的图

2、ipv6

ai_family参数指定调用者期待返回的套接口地址结构的类型。它的值包括三种:AF_INET,AF_INET6和AF_UNSPEC。如果指定AF_INET,那么函数九不能返回任何IPV6相关的地址信息;如果仅指定了AF_INET6,则就不能返回任何IPV4地址信息。AF_UNSPEC则意味着函数返回的是适用于指定主机名和服务名且适合任何协议族的地址。如果某个主机既有AAAA记录(IPV6)地址,同时又有A记录(IPV4)地址,那么AAAA记录将作为sockaddr_in6结构返回,而A记录则作为sockaddr_in结构返回

如何同时支持IPv4和IPv6连接?

在windows中AF_INET与PF_INET完全一样,而在Unix/Linux系统中,在不同的版本中这两者有微小差别

server:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXBUF 1024
int main(int argc, char **argv)
{
    int sockfd, new_fd;
    socklen_t len; 
    /* struct sockaddr_in my_addr, their_addr; */ // IPv4
    struct sockaddr_in6 my_addr, their_addr; // IPv6 
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1]; 
    if (argv[1])
        myport = atoi(argv[1]);
    else
        myport = 7838; 
    if (argv[2])
        lisnum = atoi(argv[2]);
    else
        lisnum = 2; 
    /* if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { */ // IPv4
    if ((sockfd = socket(PF_INET6, SOCK_STREAM, 0)) == -1) { // IPv6
        perror("socket");
        exit(1);
    } else
        printf("socket created/n"); 
    bzero(&my_addr, sizeof(my_addr));
    /* my_addr.sin_family = PF_INET; */ // IPv4
    my_addr.sin6_family = PF_INET6;    // IPv6
    /* my_addr.sin_port = htons(myport); */ // IPv4
    my_addr.sin6_port = htons(myport);   // IPv6
    if (argv[3])
        /* my_addr.sin_addr.s_addr = inet_addr(argv[3]); */ // IPv4
        inet_pton(AF_INET6, argv[3], &my_addr.sin6_addr);  // IPv6
    else
        /* my_addr.sin_addr.s_addr = INADDR_ANY; */ // IPv4
        my_addr.sin6_addr = in6addr_any;            // IPv6 
    /* if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) */ // IPv4
    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_in6))  // IPv6
        == -1) {
        perror("bind");
        exit(1);
    } else
        printf("binded/n"); 
    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    } else
        printf("begin listen/n"); 
    while (1) {
        len = sizeof(struct sockaddr);
        if ((new_fd =
             accept(sockfd, (struct sockaddr *) &their_addr,
                    &len)) == -1) {
            perror("accept");
            exit(errno);
        } else
            printf("server: got connection from %s, port %d, socket %d/n",
                   /* inet_ntoa(their_addr.sin_addr), */ // IPv4
                   inet_ntop(AF_INET6, &their_addr.sin6_addr, buf, sizeof(buf)), // IPv6
                   /* ntohs(their_addr.sin_port), new_fd); */ // IPv4
                   their_addr.sin6_port, new_fd); // IPv6
 
        /* 开始处理每个新连接上的数据收发 */
        bzero(buf, MAXBUF + 1);
        strcpy(buf,
               "这是在连接建立成功后向客户端发送的第一个消息/n只能向new_fd这个用accept函数新建立的socket发消息,不能向sockfd这个监听socket发送消息,监听socket不能用来接收或发送消息/n");
        /* 发消息给客户端 */
        len = send(new_fd, buf, strlen(buf), 0);
        /* 接收客户端的消息 */
        len = recv(new_fd, buf, MAXBUF, 0);
                 errno, strerror(errno));
        /* 处理每个新连接上的数据收发结束 */
    } 
    close(sockfd);
    return 0;
}

client:

#define MAXBUF 1024
int main(int argc, char **argv)
{
    int sockfd, len;
    /* struct sockaddr_in dest; */ // IPv4
    struct sockaddr_in6 dest;      // IPv6
    char buffer[MAXBUF + 1];
 
    if (argc != 3) {
        printf
            ("参数格式错误!正确用法如下:/n/t/t%s IP地址 端口/n/t比如:/t%s 127.0.0.1 80/n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    /* if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { */ // IPv4
    if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {      // IPv6
        perror("Socket");
        exit(errno);
    }
    printf("socket created/n");
 
    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    /* dest.sin_family = AF_INET; */  // IPv4
    dest.sin6_family = AF_INET6;     // IPv6
    /* dest.sin_port = htons(atoi(argv[2])); */ // IPv4
    dest.sin6_port = htons(atoi(argv[2]));     // IPv6
    /* if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) { */ // IPv4
    if ( inet_pton(AF_INET6, argv[1], &dest.sin6_addr) < 0 ) {                 // IPv6
        perror(argv[1]);
        exit(errno);
    }
    printf("address created/n");
 
    /* 连接服务器 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }
    printf("server connected/n");
 
    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF + 1);
    /* 接收服务器来的消息 */
    len = recv(sockfd, buffer, MAXBUF, 0);
 
    bzero(buffer, MAXBUF + 1);
    strcpy(buffer, "这是客户端发给服务器端的消息/n");
    /* 发消息给服务器 */
    len = send(sockfd, buffer, strlen(buffer), 0);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

     void bzero(void *s, int n);

【参数】s为内存(字符串)指针,n 为需要清零的字节数。
bzero()会将参数s 所指的内存区域前n 个字节,全部设为零值。
实际上,bzero(void *s, int n) 等价于 memset((void*)s, 0,size_tn),用来将内存块的前 n 个字节清零,但是 s 参数为指针,又很奇怪的位于 string.h 文件中,也可以用来清零字符串。

3、C C++的区别

C也有继承,结构体继承

c和c++主要区别_weixin_34293059的博客-CSDN博客

C语言和C++的区别_绘夜的博客-CSDN博客_c++和c语言的区别

在C语言中,不存在函数重载,原因为以函数名来唯一区分一个全局函数。 而在c++中 以函数名+参数列表来唯一区分函数。

C89标准的C语言不支持函数默认值,C++支持函数默认值,且需要遵循从右向左赋初始值。

malloc,free && new,delete:

①:malloc和free是函数,new和delete是运算符。

②:malloc在分配内存前需要大小,new不需要。

例如:int *p1 = (int *)malloc(sizeof(int));

           int *p2 = new int;     //int *p3 = new int(10);

malloc时需要指定大小,还需要类型转换。new时不需要指定大小因为它可以从给出的类型判断,并且还可以同时赋初始值。

③:malloc不安全,需要手动类型转换,new不需要类型转换。

④:free只释放空间,delete先调用析构函数再释放空间(如果需要)。

与第⑤条对应,如果使用了复杂类型,先析构再call operator delete回收内存。

⑤:new是先调用构造函数再申请空间(如果需要)

4、设计模式详细

单例模式

1.私有静态属性,用于存取类的唯一实例。

2.公共静态方法,用于提供对该唯一实例的存取访问,如果实例未创建,则创建该实例。

3.用于限制类再次实例化的方式。通常使用私有构建函数的方式来实现。

饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。懒汉式是用的时候加载

class CSingleton  
{  
public:  
static CSingleton* GetInstance()  
{  
     if ( m_pInstance == NULL )    
         m_pInstance = new CSingleton();  
     return m_pInstance;  
}  
private:  
    CSingleton(){};  
    static CSingleton * m_pInstance;  
};


 public class SingletonLH {
    /**
     *是否 Lazy 初始化:是
     *是否多线程安全:否
     *实现难度:易
     *描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
     *这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
     */
    private static SingletonLH instance;
    private SingletonLH (){}
 
    public static SingletonLH getInstance() {
        if (instance == null) {
            instance = new SingletonLH();
        }
        return instance;
    }
}

双重检验锁模式(double checked locking pattern),是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查

instance == null,一次是在同步块外,一次是在同步块内。为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步

块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例了

5、静态成员函数

#include <iostream>
#include <string>
 
using namespace std;
 
class test
{
private:
    static int m_value1;		//定义私有类的静态成员变量
public:
    static int m_value2;		//定义私有类的静态成员变量
 
public:
    test()
    {
    	m_value1++;
    	m_value2++;
    }
 
    int getValue()	//定义类的静态成员函数
    {
    	return m_value1;
    }
};
 
int test::m_value1 = 0;		//类的静态成员变量需要在类外分配内存空间
int test::m_value2 = 0;		//类的静态成员变量需要在类外分配内存空间
 
int main()
{
    test t1;
    test t2;
    test t3;
 
    cout << "test::m_value2 = " << test::m_value2 << endl;	//通过类名直接调用公有静态成员变量,获取对象个数
    cout << "t3.m_value2 = " << t3.m_value2 << endl;		//通过对象名名直接调用公有静态成员变量,获取对象个数
    cout << "t3.getValue() = " << t3.getValue() << endl;	//通过对象名调用普通函数获取对象个数
    system("pause");
}

 -静态成员变量属于整个类所有
    -静态成员变量的生命期不依赖于任何对象,为程序的生命周期
    -可以通过类名直接访问公有静态成员变量
    -所有对象共享类的静态成员变量
    -可以通过对象名访问公有静态成员变量
    -静态成员变量需要在类外单独分配空间

类的静态成员函数有如下特性:
    -静态成员函数是类的一个特殊的成员函数
    -静态成员函数属于整个类所有,没有this指针
    -静态成员函数只能直接访问静态成员变量和静态成员函数
    -可以通过类名直接访问类的公有静态成员函数
    -可以通过对象名访问类的公有静态成员函数
    -定义静态成员函数,直接使用static关键字修饰即可

 

class test
{
private:
    static int m_value;		//定义私有类的静态成员变量
 
public:
    test()
    {
    	m_value++;
    } 
    static int getValue()		//定义类的静态成员函数
    {
    	return m_value;
    }
}; 
int test::m_value = 0;		//类的静态成员变量需要在类外分配内存空间 
int main()
{ 
    cout << "test::m_value2 = " << test::getValue() << endl;	//通过类名直接调用公有静态成员函数,获取对象个数
    cout << "t3.getValue() = " << t3.getValue() << endl;		//通过对象名调用静态成员函数获取对象个数
    system("pause");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值