使用 SpiderMonkey 使 C++应用支持 JavaScript 脚本引擎

利用UDP Socket技术实现IP多点传送详解 IP多点传送(MulticastSocket)类IP多点传送(multicast delivery)是针对点到点的传送和广播传送两种方式而言的,它是指在一定的组内对其成员进行的广播,是一种有限的广播。组中的某个成员发出的信息,组中的其它所有成员都能收到。它是UDP Sockets的一个分支。 IP多点传送特别适合与高带宽的应用,例如在网络上发送视频和音频。随着网络带宽的不断提高和网络通讯质量的 阅读详情

翻译:dozb         英文版

这个教程的目的是演示如何使你的 C++ 应用能够解释执行 JavaScript 脚本。

SpiderMonkey

SpiderMonkey, 是 Mozilla 项目的一部分, 是一个执行JavaScript脚本的引擎. 它用 C 实现。还有一个叫做 Rhino的Java版本。

首先你要下载 SpiderMonkey 的最新版本. 下载包是以源代码形式分发的。这就需要你自己编译脚本引擎. 对于 Visual C++ 用户可以在 src-目录找到工程文件. 编译结果是叫做 'js32.dll' 的动态库.

也可以用 SpiderMonkey 在 Macintosh 和 Unix平台上. 读 ReadMe.html 来学习在其他平台如何编译。

从C++中执行 JavaScript 程序

第1步 - 创建 JavaScript 运行时环境(runtime)

JavaScript 运行时环境是调用 JS_NewRuntime 来初始化. 它分配运行时环境的所需内存。 你要指定所分配的字节数,超过这个大小碎片收集器将运行。

   JSRuntime *rt = JS_NewRuntime(1000000L);
   if ( rt == NULL )
   {
     // Do some error reporting
   }
  

第2步 - 创建一个上下文(context)

上下文指定脚本栈的大小, 私有内存的字节数被分配给指定脚本的执行栈. 每个脚本关联于自己所拥有的上下文。

但上下文被一个脚本或线程使用时,其他脚本或线程不能使用。可当脚本或线程结束,这个上下文就可以被重用于下一个脚本或线程。

用 JS_NewContext 方法创建新的上下文。一个上下文和一个运行时环境关联,你必须指定栈的大小。

    JSContext *cx = JS_NewContext(m_rt, 8192);
    if ( cx == NULL )
    {
      // Do some error reporting
    }
  

第3步 - 初始化全局对象(global object)

在脚本执行前,你必须初始化 general JavaScript 函数和创建用于大多数脚本的 object 类.

全局对象( global object) 用 JSClass 结构来描述. 初始化这个结构如下:

   JSClass globalClass =
   {
     "Global", 0,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub, JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub,
     JS_ConvertStub,  JS_FinalizeStub
   };
  

现在你可以创建 global object  且初始化它。

   JSObject *globalObj = JS_NewObject(cx, &globalClass, 0, 0);
   JS_InitStandardClasses(cx, globalObj);
  

第4步 - 执行脚本

执行脚本的一种途径是用 JS_EvaluateScript 方法.

    std::string script = "var today = Date(); today.toString();"
    jsval rval;
    uintN lineno = 0;
    JSBool ok = JS_EvaluateScript(cx, globalObj, script.c_str(), 
                                  script.length(), "script", lineno, &rval);
  

当这个脚本运行没有错误, 今天的日期被保存在 rval 中。rval 保存函数最后的执行结果。JS_EvaluateScript的返回值,运行成功是 JS_TRUE,发生错误是 JS_FALSE 。

从 rval 取回字符串的值如下所示。 这里就不演示每个细节. 当你需要的时候查看相关 API 的信息。

   JSString *str = JS_ValueToString(cx, rval);
   std::cout << JS_GetStringBytes(str);
  

第5步 - 清理脚本引擎

在应用程序结束前, 必须清理脚本引擎.

    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
  

在 C++ 中定义 JavaScript 类

在例子中使用的类如下:

   class Customer
   {
   public:
    int GetAge() { return m_age; }
    void SetAge(int newAge) { m_age = newAge; }
    std::string GetName() { return m_name; }
    void SetName(std::string newName) { m_name = newName; }

   private:
    int m_age;
    std::string m_name;
   };
  

第1步 - JavaScript类.

创建一个新的 C++ 类,可以源于将在其中使用JavaScript的类,或者创建一个新类有一个那个类类型的成员。

在 JavaScript 中用结构 JSClass 来定义类. 创建一个这个类型的静态(static)成员. 声明为 public 成员, 因为这个结构要被其他类使用。它可以被用于其他类来确定对象类型. (参考 JS_InstanceOf API)

   // JSCustomer.h
   class JSCustomer
   {
    public:
     JSCustomer() : m_pCustomer(NULL) 
     {
     }

     ~JSCustomer()
     {
       delete m_pCustomer;
       m_pCustomer = NULL;
     }

     static JSClass customerClass;

    protected:
     void setCustomer(Customer *customer) 
     {
       m_pCustomer = customer; 
     }
     
     Customer* getCustomer()
     {
       return m_pCustomer; 
     }

    private:
     Customer *m_pCustomer;

   };
   

JSClass 结构包含 JavaScript 类的名字, 一些标志和 用于引擎回调的函数名. 例如一个回调用于当引擎需要从你的类中获取一个属性时。

在C++文件的实现中定义 JSClass 结构,如下所示.

   // JSCustomer.cpp
   JSClass JSCustomer::customerClass = 
   {
    "Customer", JSCLASS_HAS_PRIVATE,
    JS_PropertyStub, JS_PropertyStub,
    JSCustomer::JSGetProperty, JSCustomer::JSSetProperty,
    JS_EnumerateStub, JS_ResolveStub, 
    JS_ConvertStub, JSCustomer::JSDestructor
   };
  

所用的回调是 JSCustomer::JSGetProperty, JSCustomer::JSSetProperty 和 JSCustomer::JSDestructor. JSGetProperty 当引擎获取属性时被回调, JSSetProperty 当引擎设置属性时被回调,JSDestructor 当JavaScript 对象被销毁时回调。

标志 JSCLASS_HAS_PRIVATE 用于指示引擎开辟内存来绑定数据到 JavaScript 对象. 你可以用 this 存储一个指向你的类的指针.

回调是C++类的静态成员函数.

   static JSBool JSGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
   static JSBool JSSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
   static JSBool JSConstructor(JSContext *cx, JSObject *obj, uintN argc, 
                               jsval *argv, jsval *rval);
   static void JSDestructor(JSContext *cx, JSObject *obj);
  

第2步 - 初始化 JavaScript 对象

创建另一个叫 JSInit 的静态方法 ,见下例. 这个方法将被应用程序调用,用来创建 JavaScript 运行时环境.

   static JSObject *JSInit(JSContext *cx, JSObject *obj, JSObject *proto);
  

实现代码如下

   JSObject *JSCustomer::JSInit(JSContext *cx, JSObject *obj, JSObject *proto)
   {
     JSObject *newObj = JS_InitClass(cx, obj, proto, &customerClass, 
                                     JSCustomer::JSConstructor, 0,
                                     JSCustomer::customer_properties, JSCustomer::customer_methods,
                                     NULL, NULL);
     return newObj;
   }
  

静态方法 JSConstructor 当你的对象被脚本实例化的时候被调用. 这个方法非常方便用于绑定你的数据到对象,通过调用 JS_SetPrivate API.

    JSBool JSCustomer::JSConstructor(JSContext *cx, JSObject *obj, uintN argc, 
                                     jsval *argv, jsval *rval)
    {
      JSCustomer *p = new JSCustomer();
     
      p->setCustomer(new Customer());
      if ( ! JS_SetPrivate(cx, obj, p) )
	return JS_FALSE;
      *rval = OBJECT_TO_JSVAL(obj);
      return JS_TRUE;
    }
  

这个构造器方法可以有多个参数, 能用于初始化你的类. 现在你已经在堆上创建了一个指针, 你也需要一种途径销毁这个指针. 这可以通过静态方法 JS_Destructor 来完成.

   void JSCustomer::JSDestructor(JSContext *cx, JSObject *obj)
   {
     JSCustomer *p = JS_GetPrivate(cx, obj);
     delete p;
     p = NULL;
   }
  

第3步 - 增加属性

增加一个类型为 JSPropertySpec 的静态数组成员 . 这个数组将包含属性信息. 再创建一个属性ID号的枚举(enum).

    static JSPropertySpec customer_properties[];
    enum
    {
     name_prop,
     age_prop
    };
  

在实现文件中初始化这个数组,代码如下

  JSPropertySpec JSCustomer::customer_properties[] = 
  { 
    { "name", name_prop, JSPROP_ENUMERATE },
    { "age", age_prop, JSPROP_ENUMERATE },
    { 0 }
  };
  

数组的最后一个元素必须是空(NULL). 每个元素包含另一个有 3 个元素的数组. 第一个元素是名字,将在 JavaScript 脚本中使用。第二个元素是属性的唯一ID号, 将被传递到回调函数中。第三个元素是一个标志,JSPROP_ENUMERATE 表示脚本中当枚举Customer对象的这个属性时是可见的,就是可以用在脚本中的for 或 in 语句中. 你可以指定 JSPROP_READONLY 属性来说明这个属性是不可以修改的.

现在你能实现获取(getting)和设置(setting)属性的回调函数.

   JSBool JSCustomer::JSGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
   {
     if (JSVAL_IS_INT(id)) 
     {
       Customer *priv = (Customer *) JS_GetPrivate(cx, obj);
       switch(JSVAL_TO_INT(id))
       {
         case name_prop:
					 
           break;
         case age_prop:
           *vp = INT_TO_JSVAL(priv->getCustomer()->GetAge());
           break;
       }
     }
     return JS_TRUE;
   }
  
   JSBool JSCustomer::JSSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
   {
     if (JSVAL_IS_INT(id)) 
     {
       Customer *priv = (Customer *) JS_GetPrivate(cx, obj);
       switch(JSVAL_TO_INT(id))
       {
         case name_prop:
           break;
         case age_prop:
           priv->getCustomer()->SetAge(JSVAL_TO_INT(*vp));
           break;
       }
     }
     return JS_TRUE;
   }
  

记得在属性回调中返回 JS_TRUE . 当你返回 JS_FALSE 将表示在你的对象中没有发现这个属性.

第4步 - 增加方法

创建类型为 JSFunctionSpec 的静态成员数组.

   static JSFunctionSpec customer_methods[];
  

在实现文件中初始化这个数组,代码如下

   JSFunctionSpec wxJSFrame::wxFrame_methods[] = 
   {
     { "computeReduction", computeReduction, 1, 0, 0 },
     { 0 }
   };
  

数组的最后一个元素必须是空(NULL). 每个元素包含另一个有 5 个元素的数组. 第一个元素是脚本中使用的函数名. 第二个元素是全局或静态成员函数名. 第三个元素是这个函数的参数个数. 最后两个元素忽略.

在类中创建一个静态方法

    static JSBool computeReduction(JSContext *cx, JSObject *obj, uintN argc, 
                                   jsval *argv, jsval *rval);
  

当函数成功就返回 JS_TRUE . 否则返回 JS_FALSE. 你的JavaScript方法实际返回值被放到了 rval 参数中.

实现这个方法的例子

   JSBool JSCustomer::computeReduction(JSContext *cx, JSObject *obj, uintN argc, 
                                       jsval *argv, jsval *rval)
   {
     JSCustomer *p = JS_GetPrivate(cx, obj);
     if ( p->getCustomer()->GetAge() < 25 )
       *rval = INT_TO_JSVAL(10);
     else
       *rval = INT_TO_JSVAL(5);
     return JS_TRUE;
   }
  

一个例子

下面的脚本使用上面创建的对象

   var c = new Customer();
   c.name = "Franky";
   c.age = 32;
   var reduction = c.computeReduction();
  

不要忘记当创建上下文的时候初始化 JavaScript 对象:

   JSObject *obj = JSCustomer::JSInit(cx, global);
  

代码

   //main.cpp 演示如何执行javascript
  #define XP_PC

#include <string>
#include <iostream>
#include <fstream>
#include <jsapi.h>

#include "JSCustomer.h"

JSClass globalClass = 
{
"Global", 0,
JS_PropertyStub, JS_PropertyStub,JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};

void main(int argc, char *argv[])
{
if ( argc < 2 )
{
std::cout << "JSExec usage" << std::endl
<< "------------" << std::endl
<< "JSExec <fileName>" << std::endl;
}

std::string script;
std::string buffer;
std::ifstream istr(argv[1]);
if ( istr.is_open() )
{
do
{
std::getline(istr, buffer);
script += buffer;
} while (!istr.fail());
}
else
{
std::cout << "JSExec error" << std::endl
<< "------------" << std::endl
<< "Can't open scriptfile " << argv[1] << std::endl;
exit(0);
}

JSRuntime *rt = JS_Init(1000000L);

if ( rt )
{
JSContext *cx = JS_NewContext(rt, 8192);
if ( cx )
{
JSObject *globalObj = JS_NewObject(cx, &globalClass, 0, 0);
if ( globalObj )
{
JS_InitStandardClasses(cx, globalObj);

// Init JSCustomer
JSCustomer::JSInit(cx, globalObj);

// Execute the script
jsval rval;
uintN lineno = 0;

JSString *str;
JSBool ok = JS_EvaluateScript(cx, globalObj, script.c_str(), script.length(), argv[1], lineno, &rval);
if ( ok == JS_TRUE )
{
str = JS_ValueToString(cx, rval);
char *s = JS_GetStringBytes(str);
std::cout << "JSExec result" << std::endl
<< "-------------" << std::endl
<< s << std::endl;
}
else
{
std::cout << "JSExec error" << std::endl
<< "------------" << std::endl
<< "Error in JavaScript file " << argv[1] << std::endl;
}
}
else
{
std::cout << "Unable to create the global object";
}
JS_DestroyContext(cx);
}
else
{
std::cout << "Unable to create a context";
}
JS_Finish(rt);
}
else
{
std::cout << "Unable to initialize the JavaScript Engine";
}
}
   //JSCustomer.h 演示Customer JavaScript类的定义
  /**
* JSCustomer.h - Example for my tutorial : Scripting C++ with JavaScript
* (c) 2002 - Franky Braem
* http://www.braem17.yucom.be
*/

#ifndef _JSCustomer_H
#define _JSCustomer_H

#include "Customer.h"

class JSCustomer
{
public:
/**
* Constructor
*/
JSCustomer() : m_pCustomer(NULL)
{
}

/**
* Destructor
*/
virtual ~JSCustomer()
{
delete m_pCustomer;
m_pCustomer = NULL;
}

/**
* JSGetProperty - Callback for retrieving properties
*/
static JSBool JSGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

/**
* JSSetProperty - Callback for setting properties
*/
static JSBool JSSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

/**
* JSConstructor - Callback for when a wxCustomer object is created
*/
static JSBool JSConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);

/**
* JSDestructor - Callback for when a wxCustomer object is destroyed
*/
static void JSDestructor(JSContext *cx, JSObject *obj);

/**
* JSInit - Create a prototype for wxCustomer
*/
static JSObject* JSInit(JSContext *cx, JSObject *obj, JSObject *proto = NULL);

static JSBool computeReduction(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);

static JSClass Customer_class;

void setCustomer(Customer *customer)
{
m_pCustomer = customer; 
}

Customer* getCustomer() 
{
return m_pCustomer; 
}

protected:

private:

Customer *m_pCustomer;

static JSPropertySpec Customer_properties[];
static JSFunctionSpec Customer_methods[];

enum
{
name_prop,
age_prop
};
};

#endif //_JSCustomer_H
   //JSCustomer.cpp 演示JSCustomer类的实现
  /**
* JSCustomer.cpp - Example for my tutorial : Scripting C++ with JavaScript
* (c) 2002 - Franky Braem
* http://www.braem17.yucom.be
*/

#include <string>

#define XP_PC
#include <jsapi.h>

//#include "Customer.h"
#include "JSCustomer.h"

JSPropertySpec JSCustomer::Customer_properties[] = 
{ 
{ "name", name_prop, JSPROP_ENUMERATE },
{ "age", age_prop, JSPROP_ENUMERATE },
{ 0 }
};

JSFunctionSpec JSCustomer::Customer_methods[] = 
{
{ "computeReduction", computeReduction, 1, 0, 0 },
{ 0, 0, 0, 0, 0 }
};

JSClass JSCustomer::Customer_class = 
{ 
"Customer", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
JSCustomer::JSGetProperty, JSCustomer::JSSetProperty,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JSCustomer::JSDestructor
};

JSBool JSCustomer::JSGetProperty(JSContext *cx, JSObject *obj, jsval id,
jsval *vp)
{
if (JSVAL_IS_INT(id)) 
{
JSCustomer *p = (JSCustomer *) JS_GetPrivate(cx, obj);
Customer *customer = p->getCustomer();
switch (JSVAL_TO_INT(id)) 
{
case name_prop:
{
std::string name = customer->GetName();
JSString *str = JS_NewStringCopyN(cx, name.c_str(), name.length());
*vp = STRING_TO_JSVAL(str);
break;
}
case age_prop:
*vp = INT_TO_JSVAL(customer->GetAge());
break;
}
}
return JS_TRUE;
}

JSBool JSCustomer::JSSetProperty(JSContext *cx, JSObject *obj, jsval id, 
jsval *vp)
{
if (JSVAL_IS_INT(id)) 
{
JSCustomer *p = (JSCustomer *) JS_GetPrivate(cx, obj);
Customer *customer = p->getCustomer();

switch (JSVAL_TO_INT(id)) 
{
case name_prop:
{
JSString *str = JS_ValueToString(cx, *vp);
std::string name = JS_GetStringBytes(str);
customer->SetName(name);
break;
}
case age_prop:
customer->SetAge(JSVAL_TO_INT(*vp));
break;
}
}
return JS_TRUE;
}

JSBool JSCustomer::JSConstructor(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval)
{
JSCustomer *priv = new JSCustomer();
priv->setCustomer(new Customer());
JS_SetPrivate(cx, obj, (void *) priv);

return JS_TRUE;
}

void JSCustomer::JSDestructor(JSContext *cx, JSObject *obj)
{
JSCustomer *priv = (JSCustomer*) JS_GetPrivate(cx, obj);
delete priv;
priv = NULL;
}

JSObject *JSCustomer::JSInit(JSContext *cx, JSObject *obj, JSObject *proto)
{
JSObject *newProtoObj = JS_InitClass(cx, obj, proto, &Customer_class, 
JSCustomer::JSConstructor, 0,
NULL, JSCustomer::Customer_methods,
NULL, NULL);
JS_DefineProperties(cx, newProtoObj, JSCustomer::Customer_properties);
return newProtoObj;
}

JSBool JSCustomer::computeReduction(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval)
{
JSCustomer *p = (JSCustomer*) JS_GetPrivate(cx, obj);
if ( p->getCustomer()->GetAge() < 25 )
*rval = INT_TO_JSVAL(10);
else
*rval = INT_TO_JSVAL(5);
return JS_TRUE;
}

   //Customer.h 演示Customer C++类的定义
#ifndef _Customer_H
#define _Customer_H

class Customer
{
public:

int GetAge() 
{
return m_age; 
}

void SetAge(int newAge)
{
m_age = newAge; 
}

std::string GetName() 
{
return m_name; 
}

void SetName(std::string newName) 
{
m_name = newName; 
}

private:

int m_age;
std::string m_name;

};

#endif
   //example.js 演示JavaScript的例子
  var c = new Customer();
c.name = "Franky";
c.age = 32;
c.computeReduction();

使用 Mozilla 的 SpiderMonkey 引擎和 Rust 构建的 JavaScript 运行时 蜘蛛火Spiderfire 是使用 Mozilla 的 SpiderMonkey 引擎和 Rust 构建的 javascript 运行时。Spiderfire 旨在破坏服务器端 javascript 运行时环境。许可该项目在 Mozilla Public License 2.0 下获得许可。可以在此处找到许可证的全文。建造有关构建 Spiderfire 的说明,请参阅此处。 立即下载

相关推荐

游戏引擎实现c++调用c#脚本功能mono.rar

这是mono所需要的所有dll文件,通过这个mono可以实现c#脚本功能,通过c++去调用c#代码,在unity游戏引擎里面就是通过mono实现c#脚本功能的。

http://www.ibm.com/developerworks/cn/linux/l-cn-spidermonkey/index.html

基于 C 语言的 JavaScript 引擎探索 使用 SpiderMonkey 脚本化您的应用 邱 俊涛, 软件工程师, 云电同方研发中心 邱俊涛,毕业于昆明理工大学计算机科学与技术专业,对机械控制、电子、人工智能、函数式编程等领域有浓厚的兴趣,对计算机科学的底层比较熟悉。喜欢 C/JAVA/Python/JavaScript 等语言。现就职于云电同方研发中心。 简介: JavaScri...

weixin_33772645的博客 416

javascript SpiderMonkey中的函数序列化如何进行

Javascript中,函数可以很容易的被序列化(字符串化),也就是得到函数的源码.但其实这个操作的内部实现(引擎实现)并不是你想象的那么简单.SpiderMonkey中一共使用过两种函数序列化的技术:一种是利用反编译器(decompiler)将函数编译后的字节码反编译成源码字符串,另一种是在将函数编译成字节码之前就把函数源码压缩并存储下来,用到的时候再解压还原. 如何进行函数序列化 在SpiderMonkey中,能将函数序列化的方法或函数有三个:Function.prototype.toString,Function.prototype.toSource,uneval.只有toString

JavaScript-C引擎嵌入开发指南

JavaScript-C引擎概览本文档提供了一个JavaScript(JS)引擎的C语言实现的概述,他介绍了你如何在你的应用程序中嵌入脚本引擎来让它们可以使用JS。有两大理由让你在应用程序中嵌入JS引擎使用脚本来自动操作你的应用程序;同时使用JS引擎脚本无论何时都可以提供跨平台的功能并消除了应用程序解决方案对平台的依赖性。受支持JavaScript版本本JS引擎支持从JS 1.0

2407

你知道 6 大 JavaScript 引擎的秘密吗?

每个 JavaScript 引擎都有其独特的优势和适用场景。V8 引擎以其高性能和广泛应用闻名,特别是在 Chrome 和 Node.js 中表现出色。SpiderMonkey 提供了强大的调试工具和灵活性,适用于复杂的 Web 应用JavaScriptCore 通过优化苹果设备性能,为 iOS 和 macOS 提供了卓越的用户体验。Chakra 的模块化设计和多线程优化使其在不同平台和嵌入式环境中表现良好。Rhino 通过与 Java 的紧密集成,为企业级应用提供了灵活性和可扩展性。

weixin_47588164的博客 2374

SpiderMonkey-让你的C++程序支持JavaScript脚本

译序有些网友对为什么D2JSP能运行JavaScript脚本程序感到奇怪,因此我翻译了这篇文章,原文在这里。这篇教程手把手教你如何利用SpiderMonkey创建一个能执行JavaScript脚本C++程序,并让JavaScript脚本操纵你的C++程序的内部数据、操作。从这篇教程可以看到在SpiderMonkey引擎的帮助下,让C++程序支持JavaScript脚本是一件很容易的事,更棒的

Sting的专栏 - Under the hood 2万+

c++与js脚本交互,C++调用JS函数JS调用C++函数

一、javascript调用c++,方法有两种 方案1: 1.html编写 <html><head></head><body><h1>TEST</h1><input type='button'name="xx3" value=调用c++函数 onclick="window.navigate('app:comma...

dkopg24406的专栏 1152

视 频 传 输 技 术

视 频 传 输 技 术许平沧--随着Internet的不断发展,人们希望在网上传送更多的多媒体信息。视频信号的传输是多媒体信息传输的核心。视频信号在计算机终端播放已不成问题,关键问题在于信号的压缩及传输技术。例如,传输MPG-1方式的普通电视信号,要求速率为120~140kbit/s;传输相当于S-VSH的MPG-2电视信号,要求500kbit/s的速率;传输双工或更高质量的信号,对带

tchaikov的专栏 2809

3G手机视频网络直播

<br />3G手机视频网络直播是指通过手机内置的摄像头,将正在拍摄的视频直接用3G网络上传到网站进行直播,让全世界的网友可以同时、无时差的欣赏即时视频现场。<br />3G手机视频直播系统是南京索品科技有限公司长期研发、重点推出的一款基于宽带无线网络技术,利用手机通过3G等无线网络,实现实时拍摄、实时传送、实时播出的一款专业视频直拍直播系统,为随时随地上传各类实时信息(文档、图片、音频、视频)提供了快捷且安全的平台,可广泛应用于:<br />1、广播电视媒体:突发事件报道、事件暗访直播、事件追踪报道和现场

sopytech的专栏 3163

OTN光传送网

什么是OTN光传送网 OTN(光传送网,OpticalTransportNetwork),OTN以波分复用技术(WDM)技术为基础,在光层组织网络的传送网,是下一代的骨干传送网。 在超大传输容量的基础上引入了SDH强大的操作、维护、管理与指配(OAM)能力,同时弥补了SDH在面向传送层时的功能缺乏和维护管理开销的不足。OTN继承了SDH和WDM的双重优势,能规避传统系统一系列问题的出现,目前已经成为宽带客户选用最多的数据传送业务技术。 芯泰通信OTNS8600传输系统 OTN光传送网简介..

m0_63251770的博客 2140

多点传送

IP 多点传送 MulticastSocket 类IP多点传送(multicast   delivery)是针对点到点的传送和广播传送两种方式而言的,它是指在一定的组内对其成员进行的广播,是一种有限的广播。组中的某个成员发出的信息,组中的其它所有成员都能收到。它是UDP   Sockets的一个分支。         IP多点传送特别适合与高带宽的应用,例如在网络上发送视频和音频。随着网络带宽的不

legion8169的专栏 1377

SQL Server 2008 高可用性视频(二)-- 日志传送

  做数据库的朋友都知道, 其实数据库的工作大致可以分为三类: 数据库设计与开发, 数据库管理, 数据库商业智能. 其中数据库管理的工作大部分是由DBA在做, DBA们除了要保证正常的数据库运行, 还要采取必要措施提升数据库的性能, 比如数据库的性能优化, 以及保证数据库系统的高可用性. 我在前面发了几篇对SQL Server数据库进行调优的文章, 下面会再开一个SQL Server高可...

weixin_30521649的博客 3万+

网上传送二进制数据的几种方法

网上传送二进制数据的几种方法 一直以来,有些无线(特别是无线Modem)或者有线网络设备无法正确发送和接收某些不可打印(不可见)二进制字符, 所以需要对二进制数据做一定的编码变换, 使之成为纯文本可见字符,常见的有两种方法,一种是采用16进制编码,另外一种是采用Base64编码。 1、16进制编码 这种编码是把1个字节拆成2个字节后发送出去,在接收端再两两还原成1字节。这种...

wpacer的博客 4628

利用UDP Sockets技术实现IP多点传送

导读:   杨绍方   摘 要 本文介绍了UDP Sockets的基本概念和IP多点传送的原理,详细讨论了Java中的相关类及使用方法,提供了一个IP多点传送的开发流程。   关键词 Java UDP Sockets    IP 多点传送 MulticastSocket 类IP多点传送(multicast delivery)是针对点到点的传送和广播传送两种方式而言的,它是指在一定的组内对其

黑客攻防 | .net 源代码下载 | ASP.NET开发 | ORACLE数据库开发 | JAVASCRIPT脚本下载 | java源码下载 899

java传参ip,操作UDP Socket技术实现IP多点传送详解[Java编程]

赞助商链接本文“操作UDP Socket技术实现IP多点传送详解[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:IP多点传送(MulticastSocket)类IP多点传送(multicast delivery)是针对点到点的传送和广播传送两种方法而言的,它是指在一定的组内对其成员举行的广播,是一...

weixin_30082413的博客 443

关闭“是否只查看安全传送的网页内容?”对话框听语音

116651人看了这个视频 返回 暂停 重播 播放 x   为您找到与问题匹配度100%的视频 播放列表   2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30....

Andrewniu的博客 1074

计算机我的电脑存储的文件,怎样把网上的视频保存到我的电脑中的自己的文档中?...

一种也是比较简单的方法:1.先观看完一段视频,在IE浏览器的”工具”中选择”internet选项”2.在”internet 临时文件夹”位置点击”设置”,在新窗口中点击”查看文件”3.在这个新打开的”Temporary Internet Files”窗口中,就可以看到很多文件了4.按照文件大小排序,文件格式后缀为flv的文件就是在土豆网上在线看完后自动保存下来的文件,这时你只需在此文件上点击鼠标右...

weixin_29029731的博客 1717
上一篇: 在Delphi和VC中创建和调用动态链接库 (转)
下一篇: 马云给雅虎员工作的精彩演讲:爱迪生欺骗了世界!
ych1
博客等级 码龄22年 5粉丝 1原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值