当前位置:  编程技术>软件工程/软件设计
本页文章导读:
    ▪apache模块开发之content hander,读取配置,输出内容替换过滤器,url域名替换过滤器           apache-replace-module  代码在https://github.com/zhwj184/apache-replace-module,示例都是从网上找的修改验证过的。apache版本2.4.4 =====================   apache module develop demo,apache 模块开.........
    ▪大话设计模式之观察者模式       观察者模式/发布-订阅模式Publish Subscribe 模式       定义了一种一对多的依赖的关系,让多个观察者看对象,同时监听某一个主体对象。这个主题对象在状态发生变化时,会通知.........
    ▪简单的Linux环境下多线程TCP服务程序框架      运行环境:Linux2.6以上 文件说明:tcputil.c --------------- TCP多线程服务框架实现                     tcputil.h --------------- 公开函数声明 使用说明:      .........

[1]apache模块开发之content hander,读取配置,输出内容替换过滤器,url域名替换过滤器
    来源: 互联网  发布时间: 2013-11-19

 

  apache-replace-module  代码在https://github.com/zhwj184/apache-replace-module,示例都是从网上找的修改验证过的。apache版本2.4.4

=====================

 

apache module develop demo,apache 模块开发

 

对输出结果进行正则替换模块, apache response content replace module,比如域名切换对所有输出url进行替换

 

apache安装完成之后,使用下面这个命令编译各个模块为so文件

 

    /usr/local/apache/bin/apxs -c helloworld.c 

    /usr/local/apache/bin/apxs -c urlreplace.c

    /usr/local/apache/bin/apxs -c urlreplacefilter.c

    /usr/local/apache/bin/apxs -c line-editor.c 

 

编译完之后会在当前目录的.libs下面生存.so的文件,正是apache的so文件。

 

    helloworld.c 是演示输出一段字符串helloworld的content handler,

    urlreplace.c 是演示读取http.conf配置之后输出的content handler,

    urlreplacefilter.c 是演示读取http.conf配置并将输出小写转为大写的输出过滤器,apache自带的demo做的修改。

    line-editor.c 是对输出内容进行正则替换等内容替换的输出过滤器,已经开源的东西,可以实现我们的功能,对输出页面的url域名进行正则替换,项目url为:http://apache.webthing.com/mod_line_edit/。

 

使用方式如下:在http.conf加入如下配置

 

    #helloworld.c 对应的配置

    LoadModule helloworld_module mylib/helloworld.so

    <Location /helloworld>

      setHandler helloworld

    </Location>

  

    #urlreplace.c的配置

    srcpath *.china.aaa.com

    descpath *.bbb.com

    LoadModule pathreplace_module mylib/urlreplace.so

    <Location /pathreplace>

      setHandler pathreplace

    </Location>

  

    #urlreplacefilter.c的配置

    LoadModule urlReplace_filter_module mylib/urlreplacefilter.so


    
[2]大话设计模式之观察者模式
    来源: 互联网  发布时间: 2013-11-19

观察者模式/发布-订阅模式Publish Subscribe 模式 

      定义了一种一对多的依赖的关系,让多个观察者看对象,同时监听某一个主体对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自动更新。

优点:观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响到另外一边的变化. 

当一个对象的改变需要同时改变其他对象时,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式. 

故事情节描述:同事小猪和同事小马趁老板出差的时候,正在查看股市行情,并告诉前台的童子喆“如果老板回来的话,记得通知我们呀!”恰巧,老板忘记带东西,于是推门而入,前台通知同事“老板回来了,关闭股市行情,继续工作!”

//通知者接口
    interface Subject
    {
        void Attach(Observer observer);
        void Detch(Observer observer);
        void Notify();
        String SubjectState
        {
            get;
            set;
        }
    }
	
//具体的通知者类可能是前台,也可能是老板
//它们也许有自己的实现方法,但是对于通知者而言,它们都是一样的,所以他们都去实现这个接口。
    class Boss:Subject 
    {
        //同事列表
        private IList <Observer> observers=new List <Observer>();
        private string action;

        //增加
        public void Attach(Observer observer)
        {
            observers.Add(observer );
        }
        //减少
        public void Detach(Observer observer)
        {
            observers.Remove(observer );
        }
        //通知
       public   void Notify()
        {
            foreach(Observer o in observers )
            o.Update();
        }
        //老板状态
        public string SubjectState
        {
            get {return action ;}
            set {action=value; }
        }
		
//前台秘书类和老板类类似	
 class Secretary : Subject 
    { 
        //同事列表
        private IList <Observer >observers=new List <Observer >();
        private string action;
        //增加
        public void Attach(Observer observer)
        {
            observers.Add(observer );
        }
        //减少
        public void Detach(Observer observer)
        {
            observers.Remove(observer );
        }
        //通知
        public void Notify()
        {
            foreach(Observer o in observers )
            o.Update();
        }
        //老板状态
        public string SubjectState
        {
            get { return action ;}
            set { action=value; }
        }
    }
	
//抽象观察者
    abstract class Observer
    {
        protected string name;
        protected Subject sub;
		
        //抽象通知者类
        public Observer(string name, Subject sub)
        {
            this.name = name;
            this.sub = sub;
        }
        public abstract void Update();
    }
	
//看股票的同事
    class StockObserver:Observer 
    {
        //抽象通知者
        public StockObserver(string name, Subject sub)
            : base(name, sub)
        { }
        //抽象通知者状态
        public override void Update()
        {
            Console.WriteLine("{0}{1}关闭股票行情,继续工作!",sub.SubjectState,name);
        }

    }
//客户端代码
	//老板胡汉三
	Boss huhansan = new Boss();
	//看股票的同事
	StockObserver tongshi1 = new StockObserver("小猪",huhansan );
	//看股票的同事
	StockObserver tongshi2 = new StockObserver("小马",huhansan );

	huhansan.Attach(tongshi1);
	huhansan.Attach(tongshi2 );

	//小马其实是没有被老板通知到的, 所以减去
	huhansan.Detach(tongshi2 );

	//老板回来
	huhansan.SubjectState = "我胡汉三回来了!";
	//发出通知
	huhansan.Notify();
        




作者:lantingxv_jing 发表于2013-4-15 22:11:59 原文链接
阅读:56 评论:0 查看评论

    
[3]简单的Linux环境下多线程TCP服务程序框架
    来源: 互联网  发布时间: 2013-11-19

运行环境:Linux2.6以上

文件说明:tcputil.c --------------- TCP多线程服务框架实现

                    tcputil.h --------------- 公开函数声明

使用说明:

                  发送消息必须采用固定的(消息大小,消息体)这种流边界方式,其中消息大小是uint32_t类型,并且是网络字节序。

                  直接调用start(监听IP, 监听端口,自定义消息处理函数)即可;主要是提供自定义的消息处理函数,原型为:

                    int msg_handler(int socket, void* buf, uint32_t n),其中: socket-接收消息的socket,buf-消息体内存,n-消息体长度。

几个关键点:

(1)发送和接收n个字节的方法,在readn()和writen()函数实现;

(2)向派生线程传递参数时,注意并发导致的同步问题,参见start()函数中的传参实现;

(3)遵循“malloc和free要成对存在于同一个函数中”,但是(2)违反了这个原则,是否有更好的解决方案?

(4)采用了回调函数机制(类似C#中的事件)来让库使用着自定义消息处理函数;(这也是为了遵循(3)采取的策略);

(5)TCP流边界,采取了(消息大小,消息体)的方式,其中消息大小为4字节无符号整数。

存在问题:

(1)性能问题,目前是直接分配与消息体大小同样的内存来接收消息体;

(2)大消息问题,目前消息不能大于int32_t的最大值;


源码:tcputil.h

#ifndef TCPUTIL_H
#define TCPUTIL_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>

ssize_t writen(int fd, void* buf, size_t n); 
ssize_t recvn(int fd, void* buf, size_t n); 

/*callback function called after received one message, 0-success, -1-error*/
typedef int (*message_handler)(int socket, void * buf, uint32_t size);

int start(uint32_t listenip, uint16_t listenport, message_handler handler);
#endif

源码:tcputil.c

/**************************************************
 *
 * $description: collection of functions 
 * $author: smstong
 * $date: Tue Apr 16 10:24:22 CST 2013
 *
 * ************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
/**************************************************
 * func: receive n bytes from socket except an error
 * params: fd - socket handle
 * 		   buf - memory space to write
 * 		   n - size of buf 
 * return: -1 - error;
 * 		   >=0 - actually retceived bytes
 *************************************************/
ssize_t recvn(int fd, void* buf, size_t n)
{
	char* ptr = (char*)buf; // position pointer
	size_t left = n;		// bytes left to read
	while(left > 0) {
		size_t nread = read(fd, ptr, left);
		if(nread<0)  {
			if(errno==EINTR) { // an error occured
				nread = 0;
			} else {
				return -1;
			}
		} else if(nread==0) { //normally disconnect, FIN segment received
			break;
		} else {
			left -= nread;
			ptr += nread;
		}
	}
	return (n-left);
}

/********************************************************
 * function: write n bytes to socket except error
 * params: fd - socket hanle 
 * 		   buf - src memory 
 * 		   n - bytes to write 
 * return: -1 - error
 * 		   >=0 - bytes actually written
 * ******************************************************/
ssize_t writen(int fd, void* buf, size_t n)
{
	char* ptr = (char*)buf;
	size_t left = n;
	while(left > 0) {
		size_t nwrite = write(fd, ptr,left);
	    if(nwrite<0) {
			if(errno==EINTR) {
				nwrite = 0;
			} else {
				return -1;
			}
		} else if(nwrite==0) {
			break;
		} else {
			left -= nwrite;
			ptr += nwrite;
		}	
	}
	return (n-left);
}

static void * thread_f(void *); //thread function 
typedef int (*message_handler)(int, void *, uint32_t); // callback function called after received one message

/*************************************************************
 *
 * one thread per connection frameset
 *
 * ***********************************************************/

// thread function's args
struct thread_arg {
	int socket;
	message_handler msg_handler;
};

int start(uint32_t listenip, uint16_t listenport, message_handler handler)
{	
	int    listenfd, connfd;
	struct sockaddr_in     servaddr;
	char    buff[4096];
	int     n;

	if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
		printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
		exit(0);
	}

	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(listenip);
	servaddr.sin_port = htons(listenport);

	if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
		printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
		return -1;
	}

	if( listen(listenfd, 10) == -1){
		printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
		return -1;
	}

	printf("======waiting for client's request======\n");
	while(1){
		if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
			printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
			continue;
		}
		/* create a new thread to handle this connection */
		pthread_t tid = 0;
		int rc = 0;
		struct thread_arg *parg = malloc(sizeof(struct thread_arg));
		if(NULL==parg) {
			printf("error malloc: %s\n", strerror(errno));
			return -1;
		}
		parg->socket = connfd;
		parg->msg_handler = handler;
		if(0 != (rc=pthread_create(&tid, NULL, thread_f, parg))) {
			printf("%s: %s\n", __func__, strerror(rc));
		}
		printf(" create thread %u to handle connection %d \n", tid, connfd);	
	}
	close(listenfd);
	return 0;
}
/***************************
 * fun: receive one message
 * params: connfd - socket handle
 * return: 0 - success;
 * 		   -1 - error
 *
 * **************************/
static int recv_one_message(int connfd, message_handler post_recv_one)
{
	uint32_t msg_len = 0;		 /* message length */

	/* recv length */
	if(4 != recvn(connfd, &msg_len, 4)) { // something wrong
		return -1;
	}
	msg_len = ntohl(msg_len);

	/* recv body */
	if(msg_len > 0x7FFFFFFF) {
		printf("message body to large\n");
		return -1;
	}
	char* buf = malloc(msg_len);/* allocate memory for message body*/
	if(NULL == buf) {
		printf("%s: malloc failed!\n", __func__);
		return -1;
	}
	if(msg_len != recvn(connfd, buf, msg_len)) {
		free(buf);
		return -1;
	}
	if(0!=post_recv_one(connfd, buf, msg_len)) { // callback
		free(buf);
		return -1;
	}
	free(buf);
	return 0;
}
/* thread to handle a connection */
static void * thread_f(void * arg) 
{
	printf(" enter thread %u\n", pthread_self());
	struct thread_arg targ = *((struct thread_arg*)arg); 
	int connfd = targ.socket;
	message_handler post_recv_one = targ.msg_handler;
	free(arg);

	int i = 0;
	while(1) {
		if(0 != recv_one_message(connfd, post_recv_one)) {
			break;
		}
		printf("message : %d\n", i++);
	}
	close(connfd);
	printf(" leave thread %u\n", pthread_self());
}


源码:测试例子 server.c,接收消息写入文件data中。

#include "tcputil.h"
#include <stdio.h>

/* callback called after one message received. */
int msg_handler(int fd, void* buf, uint32_t n)
{
    char* msg = (char*)buf;
    FILE* fp = fopen("data", "w");
    if(NULL == fp) {
        printf("%s\n", strerror(errno));
        fclose(fp);
        return -1; 
    }   
    if(n != fwrite(msg, 1, n, fp)) {
        printf("write error:\n");
        fclose(fp);
        return -1; 
    }   
    fclose(fp);
    return 0;
}

int main(int argc, char** argv)
{
    start(0,6666, msg_handler);
}
             
源码:客户端程序 C#编写

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SendTcpMsg(File.ReadAllBytes(@"F:\核心软件备份\TomatoWin2k3.SP2.R2.iso"));
        }
        static void SendTcpMsg(Byte[] msgBody) 
        {
            Socket sock = null;
            try
            {
                sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sock.Connect("172.16.35.135", 6666);
                byte[] msgHead = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(msgBody.Length));
                sock.Send(msgHead);
                sock.Send(msgBody);
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            finally
            {
                if(sock!=null)
                    sock.Close();
            }
        }
    }
}



作者:smstong 发表于2013-4-16 16:29:33 原文链接
阅读:0 评论:0 查看评论

    
最新技术文章:
▪主-主数据库系统架构    ▪java.lang.UnsupportedClassVersionError: Bad version number i...    ▪eclipse项目出现红色叉叉解决方案
▪Play!framework 项目部署到Tomcat    ▪dedecms如何做中英文网站?    ▪Spring Batch Framework– introduction chapter(上)
▪第三章 AOP 基于@AspectJ的AOP    ▪基于插件的服务集成方式    ▪Online Coding开发模式 (通过在线配置实现一个表...
▪观察者模式(Observer)    ▪工厂模式 - 程序实现(java)    ▪几种web并行化编程实现
▪机器学习理论与实战(二)决策树    ▪Hibernate(四)——全面解析一对多关联映射    ▪我所理解的设计模式(C++实现)——解释器模...
▪利用规则引擎打造轻量级的面向服务编程模式...    ▪google blink的设计计划: Out-of-Progress iframes    ▪FS SIP呼叫的消息线程和状态机线程
▪XML FREESWITCH APPLICATION 实现    ▪Drupal 实战    ▪Blink: Chromium的新渲染引擎
▪(十四)桥接模式详解(都市异能版)    ▪你不知道的Eclipse用法:使用Allocation tracker跟...    ▪Linux内核-进程
▪你不知道的Eclipse用法:使用Metrics 测量复杂度    ▪IT行业为什么没有进度    ▪Exchange Server 2010/2013三种不同的故障转移
▪第二章 IoC Spring自动扫描和管理Bean    ▪CMMI简介    ▪目标检测(Object Detection)原理与实现(六)
▪值班总结(1)——探讨sql语句的执行机制    ▪第二章 IoC Annotation注入    ▪CentOS 6.4下安装Vagrant
▪Java NIO框架Netty1简单发送接受    ▪漫画研发之八:会吃的孩子有奶吃    ▪比较ASP和ASP.NET
▪SPRING中的CONTEXTLOADERLISTENER    ▪在Nginx下对网站进行密码保护    ▪Hibernate从入门到精通(五)一对一单向关联映...
▪.NET领域驱动设计—初尝(三:穿过迷雾走向光...    ▪linux下的块设备驱动(一)    ▪Modem项目工作总结
c/c++开源软件 iis7站长之家
▪windows下用putty上传文件到远程Linux方法    ▪iBatis和Hibernate的5点区别    ▪基于学习的Indexing算法
▪设计模式11---设计模式之中介者模式(Mediator...    ▪带你走进EJB--JMS编程模型    ▪从抽象谈起(二):观察者模式与回调
▪设计模式09---设计模式之生成器模式(Builder)也...    ▪svn_resin_持续优化中    ▪Bitmap recycle方法与制作Bitmap的内存缓存
▪Hibernate从入门到精通(四)基本映射    ▪设计模式10---设计模式之原型模式(Prototype)    ▪Dreamer 3.0 支持json、xml、文件上传
▪Eclipse:使用PMD预先检测错误    ▪Jspx.net Framework 5.1 发布    ▪从抽象谈起(一):工厂模式与策略模式
▪Eclipse:使用CheckStyle实施编码标准    ▪【论文阅读】《Chain Replication for Supporting High T...    ▪Struts2 Path_路径问题
▪spring 配置文件详解    ▪Struts2第一个工程helloStruts极其基本配置    ▪Python学习入门基础教程(learning Python)--2 Python简...
▪maven springmvc环境配置    ▪基于SCRUM的金融软件开发项目    ▪software quality assurance 常见问题收录
▪Redis集群明细文档    ▪Dreamer 框架 比Struts2 更加灵活    ▪Maven POM入门
▪git 分支篇-----不断更新中    ▪Oracle非主键自增长    ▪php设计模式——UML类图
▪Matlab,Visio等生成的图片的字体嵌入问题解决...    ▪用Darwin和live555实现的直播框架    ▪学习ORM框架—hibernate(二):由hibernate接口谈...
▪(十)装饰器模式详解(与IO不解的情缘)    ▪无锁编程:最简单例子    ▪【虚拟化实战】网络设计之四Teaming
▪OSGi:生命周期层    ▪Javascript/Jquery——简单定时器    ▪java代码 发送GET、POST请求
▪Entity Framework底层操作封装(3)    ▪HttpClient 发送GET、POST请求    ▪使用spring框架,应用启动时,加载数据
▪Linux下Apache网站目录读写权限的设置    ▪单键模式的C++描述    ▪学习ORM框架—hibernate(一):初识hibernate
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3