C++ rtmp livestream 流媒体

海阔天空 张翼飞翔

我的学习笔记。--我喜欢这里,因为这里安静,无广告骚扰。
随笔 - 82, 文章 - 2, 评论 - 126, 引用 - 0
数据加载中……

基于ACE环境的非阻塞模式服务器实现

关键字:ACE 自适配通信环境  非阻塞模式 服务器代码 C++ 实现
网络上大部分文章都是介绍用VC++6来编译ACE的。但ACE的VC6版本最多支持到 5.5.1。 之后的版本不支持 VC6了也没有ace.dsw文件。看这些早期的文章让我走了一些弯路,现在我把我用VC8编译ACE的和使用ACE环境的方法整理如下:
1、到http://download.dre.vanderbilt.edu/下载ACE的FULL版本,将ACE-5.6.zip解压到所需的安装目录,此处以D:\Program Files\ACE_wrappers为例,解压后形成ACE_wrappers文件夹,因此ACE将会存在于ACE_wrappers\ace目录中。
2、在ACE_wrappers\ace目录中创建一个头文件,命名为config.h,其内容为:
#include "ace/config-win32.h"
3、在VC8中打开ACE的工程文件(ACE_wrappers\ace\ACE_vc8.vcproj,如果没有该文件请重新下载完整版本),在release和debug两种编译方式下进行编译,编译完毕后在ACE_wrappers \lib下得到相应的库文件(ACE.dll、ACE.lib 和 ACEd.dll、ACEd.lib),其中ACE.dll 、ACE.lib是由release版生成的,ACEd.dll、ACEd.lib是由debug版生成的。
4、同样打开ACE_vc8_Static.vcproj编译可生成ACEs.lib、 ACEsd.lib、ACE_RMCasts.lib、ACE_RMCastsd.lib、TMCasts.lib、TMCastsd.lib。到此,ACE编译完成,
5、打开VS.NET2005创建一个VC++空项目,取个名字ACE_Server,请不要创建FMC、Win32控制台或CLR控制台项目,他们编译后的程序需要.Net Framework的支持。
6、工具->选项->项目和解决方案->VC++目录->显示以下内容的目录,选中"包含文件",在列表中添加上D:\Program Files\ACE_wrappers。
7、继续点“显示以下内容的目录”,选中“库文件”,在列表中添加D:\Program Files\ACE_wrappers\lib。
8、在系统环境的变量 path中加入D:\Program Files\ACE_wrappers\lib,否则在运行程序的时候碰到寻找ace.dll或者aced.dll的问题。
9、在VC8空项目里面添加一个server.cpp文件copy如下内容:

#ifndef WIN32
#define WIN32
#endif
#ifdef _DEBUG
#pragma comment (lib,
"aced.lib")
#else
#pragma comment (lib,
"ace.lib")
#endif

#include 
"ace/SOCK_Acceptor.h"
#include 
"ace/SOCK_Stream.h"
#include 
"ace/log_msg.h"

#define SIZE_DATA 18
#define SIZE_BUF 1024
#define NO_ITERATIONS 5
class Server
{
public:
    Server (
int port): server_addr_(port),peer_acceptor_(server_addr_)
    
{
        data_buf_
= new char[SIZE_BUF];
    }

    
//Handle the connection once it has been established. Here the
    
//connection is handled by reading SIZE_DATA amount of data from the
    
//remote and then closing the connection stream down.
    int handle_connection()
    
{
        
// Read data from client
        for(int i=0;i<NO_ITERATIONS;i++)
        
{
            
int byte_count=0;
            
if( (byte_count=new_stream_.recv_n (data_buf_, SIZE_DATA, 0))==-1)
                ACE_ERROR ((LM_ERROR, 
"%p\n""Error in recv"));
            
else
            
{
                data_buf_[byte_count]
=0;
                ACE_DEBUG((LM_DEBUG,
"Server received %s \n",data_buf_));
            }

        }

        
// Close new endpoint
        if (new_stream_.close () == -1)
            ACE_ERROR ((LM_ERROR, 
"%p\n""close"));
        
return 0;
    }

    
//Use the acceptor component peer_acceptor_ to accept the connection

    
//into the underlying stream new_stream_. After the connection has been
    
//established call the handle_connection() method.
    int accept_connections ()
    
{
        
if(peer_acceptor_.get_local_addr (server_addr_) == -1)
            ACE_ERROR_RETURN((LM_ERROR,
"%p\n","Error in get_local_addr"),1);
        ACE_DEBUG ((LM_DEBUG,
"Starting server at port %d\n",
            server_addr_.get_port_number ()));
        
// Performs the iterative server activities.
        while(1)
        
{
            ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
            
if (peer_acceptor_.accept (new_stream_, &client_addr_, &timeout)== -1)
            
{
                ACE_ERROR ((LM_ERROR, 
"%p\n""accept"));
                
continue;
            }

            
else
            
{
                ACE_DEBUG((LM_DEBUG,
                    
"Connection established with remote %s:%d\n",
                    client_addr_.get_host_name(),client_addr_.get_port_number()));
                
//Handle the connection
                handle_connection();
            }

        }

    }

private:
    
char *data_buf_;
    ACE_INET_Addr server_addr_;
    ACE_INET_Addr client_addr_;
    ACE_SOCK_Acceptor peer_acceptor_;
    ACE_SOCK_Stream new_stream_;
}
;

int main (int argc, char *argv[])
{
    Server server(
8080);
    server.accept_connections();
    getchar();
    
return 0;
}



9、重新创建一个空VC8空项目名字叫ACE_Client,添加一个client.cpp文件,copy如下类容
#ifndef WIN32
#define WIN32
#endif
#ifdef _DEBUG
#pragma comment (lib,
"aced.lib")
#else
#pragma comment (lib,
"ace.lib")
#endif

#include 
"ace/log_msg.h"
#include 
"ace/SOCK_Connector.h"
#include 
"ace/INET_Addr.h"
#define SIZE_BUF 128
#define NO_ITERATIONS 5

class Client
{
public:
    Client(
char *hostname, int port):remote_addr_(port,hostname)
    
{
        data_buf_
="Hello from Client";
    }


    
//Uses a connector component `connector_ ?to connect to a
    
//remote machine and pass the connection into a stream
    
//component client_stream_
    int connect_to_server()
    
{
        
// Initiate blocking connection with server.
        ACE_DEBUG ((LM_DEBUG, "(%P|%t) Starting connect to %s:%d\n",
            remote_addr_.get_host_name(),remote_addr_.get_port_number()));
        
if (connector_.connect (client_stream_, remote_addr_) == -1)
            ACE_ERROR_RETURN ((LM_ERROR,
"(%P|%t) %p\n","connection failed"),-1);
        
else
            ACE_DEBUG ((LM_DEBUG,
"(%P|%t) connected to %s\n",
            remote_addr_.get_host_name ()));
        
return 0;
    }



    
//Uses a stream component to send data to the remote host.
    int send_to_server()
    
{
        
// Send data to server
        for(int i=0;i<NO_ITERATIONS; i++)
        
{
            
if (client_stream_.send_n (data_buf_,
                ACE_OS::strlen(data_buf_)
+10== -1)
            
{
                ACE_ERROR_RETURN ((LM_ERROR,
"(%P|%t) %p\n","send_n"),0);
                
break;
            }

        }

        
//Close down the connection
        close();
    }

    
//Close down the connection properly.
    int close()
    
{
        
if (client_stream_.close () == -1)
            ACE_ERROR_RETURN ((LM_ERROR,
"(%P|%t) %p\n","close"),-1);
        
else
            
return 0;
    }

private:
    ACE_SOCK_Stream client_stream_;
    ACE_INET_Addr remote_addr_;
    ACE_SOCK_Connector connector_;
    
char *data_buf_;
}
;


int main (int argc, char *argv[])
{
    Client client(
"127.0.0.1",8080);
    client.connect_to_server();
    client.send_to_server();
    
return 0;
}


posted on 2008-04-22 17:14 ZhangEF 阅读(1172) 评论(3)  编辑  收藏 所属分类: C/C++Socket

评论

# re: 基于ACE环境的非阻塞模式服务器实现  回复  更多评论   

这个好像是阻塞模式吧,没看到体现非阻塞的啊。
是不是ACE_SOCKET_STREAM本身就是非阻塞的?
2009-07-15 22:16 | guhan

# re: 基于ACE环境的非阻塞模式服务器实现  回复  更多评论   

ACE帮我们封装了许多细节, 这样写就实现非阻塞模式了,代码简洁多了.
2010-02-02 18:28 | ZhangEF

# re: 基于ACE环境的非阻塞模式服务器实现  回复  更多评论   

@guhan
ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);所谓非阻塞应该是说的这里 设置了timeout吧 过了ACE_DEFAULT_TIMEOUT设定的时间 函数就会返回
2011-02-25 16:50 | wulf