小技巧、小经验(3)

(1)、多态作用:

多态的意义在于,它实现了接口重用(同一的表达式),接口重用带来的好处是程序更易于扩展,代码重用更加方便,更具有灵活性,也就能真实地反映现实世界。


(2)、设置默认的IP和端口

    ServerIP.SetAddress(127, 0, 0, 1);//CIPAddressCtrl
    ServerPort.SetWindowText("6001");//CEdit


(3)、进程间通信方式

1. 管道pipe
   一般不用匿名管道做进程通信,使用2
2. 命名管道FIFO
   推荐使用,和socket相比,不占用端口号,虽然也支持不同机器通信,但一般只用于本机进程通信,支持数据双向或单向传输
3. 内存映射MemoryMapping
   适用于共享数据的情况,与管道和socket相比,缺点是不能被动得到通知,只能主动去访问共享数据。假如有A,B两个进程,A修改或读取共享内存的数据,B并不能知道,B只能通过自己主动去访问共享内存,得知数据变化。而管道和socket,A可以向B发送数据,B能够立即知道,反过来也一样
4. 消息队列MessageQueue
   没用过
5. 共享存储SharedMemory
   和3相似
6. 信号量Semaphore
   一般只用于进程或线程同步
7. 套接字Socket
   和管道相比,缺点是占用端口号,优点是适合不同机器间通信,最常见的例子就是远程控制工具


(4)TCP滑动窗口问题:

    前段时间研究分布式时写了一个可扩展的服务器组程序,服务器组之间通信时老是达不到想要的性能。后来抓包排查,原来是TCP滑动窗口引起的问题,本来是很基础的东西,奈何当初没有太在意,导致错误的产生,现在详细写出来,忘不太清楚者警惕!
   滑动窗口的基本情况我有必要废话一下。TCP通信为了保证可靠性,每次发送的数据都需要得到对方的ACK才确认对方收到了(仅保证对方TCP接收缓冲收到数据了,但不保证对方应用程序取到数据了),这时如果每次发送一次就要停下来等着对方的ACK消息,显然是一种极大的资源浪费和低下的效率,这时就有了滑动窗口的出现。
发送方的滑动窗口维持着当前发送的帧序号,已发出去帧的计时器,接收方当前的窗口大小(由接收方ACK通知,大体等于接收缓冲大小-未处理的消息包),接收方滑动窗口保存的有已接收的帧信息、期待的下一帧的帧号等,至于滑动窗口的具体工作原理这里就不说了。
   一个socket有两个滑动窗口(一个sendbuf、一个recvbuf),两个窗口的大小是通过setsockopt函数设置的,现在问题就出在这里,通过抓包显示,设置的窗口大小没有生效,最后排查发现setsockopt函数是后来加上的,写到了listen函数的后面,这样每次accept出的socket并没有继承得到主socket设置的窗口大小,无语啊……
   解决办法:setsockopt函数提前到listen函数之前,这样在服务器程序启动监听前recvbuf就已经有了,accept后的链接得到的就是recvbuf了,启动程序运行,抓包显示窗口已经是指定的大小了。
   网络编程其实很简单,任何人都可以写出一套自己的服务器框架,但是细节决定成败,性能的高低有时候就是几个小细节决定的(当然这里说的这个问题是个编程错误,不属于可优化的细节问题)

(5)为什么select不如IOCP?

我们知道,LINUX为了解决SELECT或者POLL函数调用效率不够高的问题,退出了一个内核调用函数EPOLL,而WINDOWS下的完成端口更进一步,EPOLL只是在有变化的时候通知投递者,而完成端口干脆连部分变化也一起给处理了。 SELECT效率为什么不如EPOLL,这就需要操作系统知识了,因为操作系统对句柄的管理是全局的,而很多操作是通过驱动来完成的,SELECT的原理是,对SELECT指定的SOCKET队列进行循环扫描,直大发生指定变化或者超时,注意是循环,特例就是指定超时时间为0,这个时候,SELECT的效率同样是很高的,而当变化发生时,由于调度的关系,这个时候SELECT可能并没有被调度运行,导致了时间的延迟,具体请参考操作系统原理中CPU的分配策略。而引入完成端口,则通过在内核开启线程,在内核级别对需要监视的句柄进行监视,可以在驱动投递信息的第一时间发现,并立即使用内核线程进行处理,例如,TCP协议栈接收到了一个数据包,那么这个关联的句柄发生的变化会立即通知给内核对应线程,内核线程将立即处理

总结上面说的就是,SELECT由于轮询SOCKET队列和CPU调度问题,导致SELECT响应事件有延迟。而IOCP则是立即发现(异步的通知)。


(6)知名博客

http://blog.csdn.net/dbzhang800/article/details/6460229


(7)

    #include <stdio.h>   
    #include <stdlib.h>   
    #include <string.h>   
    #include "iostream.h"   
       
       
    int width=512;   
    int height=384;   
       
       
       
    //int rgb_2_yuv422(FILE *ifp, FILE *ofp);   
    int rgb_2_yuv420(char *name, FILE *ofp);   
    //int rgb_2_yuv420(char *name, char *outname);   
    //int select_option(void);   
       
    void main()   
    {       
         int  result = 0;   
         int  i=0;   
     //FILE *inf[10];   
         FILE *outf;   
        char  fname1[10]="";   
      /*if (result == -1)   
      {  
      cout<< "You did not change anything!!\n";  
      }  
      else if (result == 3)   
      {  
      cout<< "You convert from RGB to YUV422!!\n";  
      }  
      else if (result == 4)   
      {  
      cout<< "You convert from RGB to YUV420!!\n";  
      }*/   
         
      printf("please inout the outfile name:\n");   
      scanf("%s",fname1);   
       outf=fopen(fname1,"wb");   
        for(i=0;i<10;i++)   
        {   
        char fname[256]="";   
        int re=0;   
        printf("please input the infile name:\n");   
        scanf("%s",fname);   
        re=rgb_2_yuv420(fname,outf);   
        if(re!=4)   
        printf("wrong!\n");   
       
        }   
    fclose(outf);   
        
    }   
       
       
    //Convert from RGB to YUV 4:2:0   
    int rgb_2_yuv420(char *name, FILE *ofp)   
       
    {   FILE *ifp;   
        ifp = fopen(name, "rb");   
        int i,j;   
        int R, G, B;   
        int Y, U, V;   
        //Allocate memory for input and output buffers.   
        unsigned char *RGBBuffer = new unsigned char[width*height*3];//[228*352*3];   
        unsigned char *YBuffer = new unsigned char[width*height];//[288*352];   
        unsigned char *UBuffer = new unsigned char[width*height/4];//[288*352/4];   
        unsigned char *VBuffer = new unsigned char[width*height/4];//[288*352/4];   
        int *ULine = (new int[width+2])+1;   
        int *VLine = (new int[width+2])+1;   
        ULine[-1]=ULine[width]=128;   
        VLine[-1]=VLine[width]=128;   
        int *UImage = (new int[(height+2)*(width+2)])+(width+2)+1;   
        int *VImage = (new int[(height+2)*(width+2)])+(width+2)+1;   
       
        fread(RGBBuffer, sizeof(char), width*height*3, ifp);   
       
        for (i=0; i<height; ++i)   
        {   
            int RGBIndex = 3*width*i;   
            int YIndex   = width*(height-i);   
       
            for ( j=0; j<width; ++j)   
            {   
                R = RGBBuffer[RGBIndex++];   
                G = RGBBuffer[RGBIndex++];   
                B = RGBBuffer[RGBIndex++];   
                //Convert RGB to YUV   
                Y = (unsigned char) (0.299 * R + 0.587 * G +  0.114 * B );   
                U = (unsigned char)(-0.1687 * R -  0.3313 * G +  0.5 * B+128);   
                V = (unsigned char)(0.5 * R -  0.4187 * G - 0.0813 * B + 128);    
                   
       
                //Clip Y ready for output & copy UV ready for filtering   
                YBuffer[YIndex--] = static_cast<unsigned char>( (Y<0) ? 0 : ((Y>255) ? 255 : Y) );   
                VLine[j] = V;   
                ULine[j] = U;   
            }   
       
            for ( j=0; j<width; j+=2)    
            {   
                //Filter line   
                VImage[i*(width+2)+j] = ((VLine[j-1]+2*VLine[j]+VLine[j+1]+2)>>2);   
                UImage[i*(width+2)+j] = ((ULine[j-1]+2*ULine[j]+ULine[j+1]+2)>>2);   
       
            }   
       }   
       
       for (i=0; i<height; i+=2)    
       {   
           int UVIndex = (width*(height-i))/4;   
           for ( j=0; j<width; j+=2)    
           {   
               //Filter vertically and subsample by 2   
               //U = UImage[line*UVWidth+pixel];   
               //V = VImage[line*UVWidth+pixel];   
           //  V = ((VLine[j-1]+2*VLine[j]+VLine[j+1]+2)>>2);   
        //   U = ((ULine[j-1]+2*ULine[j]+ULine[j+1]+2)>>2);   
       
               V = ((VImage[(i-1)*(width+2)+j]+2*VImage[i*(width+2)+j]+VImage[(i+1)*(width+2)+j]+2)>>2);   
               U = ((UImage[(i-1)*(width+2)+j]+2*UImage[i*(width+2)+j]+UImage[(i+1)*(width+2)+j]+2)>>2);   
       
               //Clip and copy UV to output buffer   
               VBuffer[UVIndex--] = static_cast<unsigned char>( (V<0) ? 0 : ((V>255) ? 255 : V) );   
               UBuffer[UVIndex] = static_cast<unsigned char>( (U<0) ? 0 : ((U>255) ? 255 : U) );    
                  
            }   
       }   
    //Write frames of Y then U then V components   
       fwrite(YBuffer, sizeof(char), width*height, ofp);   
       fwrite(VBuffer, sizeof(char), width*height/4, ofp);   
       fwrite(UBuffer, sizeof(char), width*height/4, ofp);   
       
        return 4;   
        fclose(ifp);   
        //fclose(ofp);   
    }  

(8)、手动设置linux虚拟机ip地址
如果虚拟机不能自动获取IP,只能手动配置,配置方法如下:

输入命令

#vi /etc/sysconfig/network-scripts/ifcfg-eth0 [编辑网卡的配置文件]

输入上述命令后回车,打开配置文件,使用方向键移动光标到最后一行,按字母键“O”,进入编辑模式,输入以下内容:

IPADDR=192.168.4.10
NETMASK=255.255.255.0
GATEWAY=192.168.4.1
另外光标移动到”ONBOOT=no”这一行,更改为ONBOOT=yes
“BOOTPROTO=dhcp”,更改为BOOTPROTO=none

完成后,按一下键盘左上角ESC键,输入:wq 在屏幕的左下方可以看到,输入回车保存配置文件。

之后需要重启一下网络服务,命令为
#service network restart
网络重启后,eth0的ip就生效了,使用命令#ifconfigeth0 查看

接下来检测配置的IP是否可以ping通,在物理机使用快捷键WINDOWS+R 打开运行框,输入命令cmd,输入ping 192.168.4.10 进行检测,ping通说明IP配置正确。
备注:我所在的物理机网段为192.168.4.0 网段。大家做实验的时候根据自己的环境进行设定,保持虚拟机和物理机在同一网段即可。


(9)、linux 下遍历文件夹下的所有文件

http://blog.csdn.net/wallwind/article/details/7528474


(10)、ActiveMQ实现负载均衡+高可用部署方案

http://www.open-open.com/lib/view/open1400126457817.html


(11)、"No IConnectionFactory implementation found for connection URI"错误

发现少了Ionic.Zlib.dll,添加了程序就通过了。


(12)、

gSOAP 安装过程

系统环境
操作系统:CentOS 6.3
gSOAP:gsoap_2.8.17.zip

1. 解压 gsoap_2.8.17.zip,进入 gsoap-2.8 目录。

2. 执行configure
# ./configure

如果出现如下问题:
configure: error: C++ compiler cannot create executables
原因是没安装了g++,重新安装后问题解决。

3. 执行 make 
# make
如果出现如下问题:
../../ylwrap: line 111: yacc: command not found

解决办法:安装 byacc 。
再执行 make,如果出现如下问题:
missing: line 46: flex: command not found
解决办法:安装 flex ,然后需要重新运行 ./configure,再执行 make 。
如果出现如下问题:
.../usr/bin/ld: cannot find -ly
解决办法:安装 bison
至此,make通过。

4. 然后安装
# make install
安装成功,结束。



(13)、bash: ./configure: 权限不够
linux下运行一个文件时 提示权限不够,说明这个文件没有可执行权限
我们可以在属性里面手动为这个文件加上可执行权限也可以使用命令的方式
命令方式:
例如:   bash: ./configure: 权限不够
给文件加上可执行权限: chmod +x configure
再输入 ./configure 就可以了;


(14)、shell脚本需要注意空格,少了空格会影响判断结果

read -p "please input (Y/N):" yn
["$yn"=="Y" -o "$yn"=="y"] && echo"OK!" && exit 0

改成

read -p "please input (Y/N):" yn
[ "$yn"=="Y" -o "$yn"=="y" ] && echo "OK!" && exit 0

(15)、linux系统查看所有服务的命令  

chkconfig --list

http://blog.163.com/ray_lisa@126/blog/static/26461550201278122584/


(16)、C语言获取文件状态标识,判断文件是否打开的状态。

文件结构体中有状态标识符,可以用来判断文件是的打开状态。windows下面是_flag,linux上面是flags,solaris上面的结构体变量中没有状态标识符。但是linux和solairs上面都可以用fileno来获得文件的描述符,然后用fcntl来获得文件的状态标识。fcntl(fd,F_GETFL),大概是这样写。


(17)、Linux检测U盘

http://bbs.chinaunix.net/thread-4114903-1-1.html

http://blog.csdn.net/absurd/article/details/1587938


(18)、Linux scp复制文件,不需要输入密码的技巧

http://www.cnblogs.com/zhuawang/p/5046387.html


(19)、用C++写一个返回字符串的自定义函数

#include<string>
#include<iostream>

using namespace std;


string fun1(int a)
{

	string str = "a";
	return str;
}


char* fun2(int a)
{
	char *p = new char[2];
	p[0] = 'a';
	p[1] = '\0';
	return p;
}


void main()
{

	cout<<fun1(4)<<endl;

	char *p = fun2(4);
	cout<<p<<endl;
	delete [] p;

}

(20)、win7下安装VC6.0,在XPsp3下安装vc++6.0sp6企业版时总提示找不到acmboot.exe?解决方法:


1、在D盘新建文件夹 VFP ,把安装盘中所有文件拷贝到新建的文件夹中。
2、打开文件夹VFP,找到setup文件夹,打开它。在其中找到ACMSETUP.exe及VFP98PRO.stf两个文件。(可能VFP98PRO.stf文件版本不同有所区别,但是只要找到是后缀名为.stf就行了)
3、记录下这两个文件的路径。(如果完全按我上面的做,则路径是:  d:\vfp\setup)
4、在 开始\运行 里输入cmd,回车打开命令提示符窗口。
5、输入 cd: d:\vfp\setup 后回车
6、输入 ACMSETUP.EXE /t VFP98PRO.stf 回车后就会弹出安装界面,按照向导提示安装即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值