远程连接失败,与Facebook聊天连接

编程入门 行业动态 更新时间:2024-10-28 20:20:47
本文介绍了远程连接失败,与Facebook聊天连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我试图在我的jQuery Mobile上集成Facebook聊天,并考虑以下

但是当我打开服务器(punjab),并将以下必要的凭据放在与facebook相关的javascript中,我得到远程连接失败错误任何人都可以告诉我什么失踪。

JID:XXX@chat.facebook 密码:< FacebookPassword>

outgoing&传入请求

SENT:< body rid ='1283282620'xmlns ='http://jabber/protocol/httpbind 'to ='chat.facebook'xml:lang ='en'wait ='300'hold ='1'content ='text / xml; charset = utf-8'ver ='1.6'xmpp:version ='1.0'xmlns:xmpp ='urn:xmpp:xbosh'/> RECV:< body xmlns ='http://jabber/protocol/httpbind'type ='terminate'condition ='remote-connection-failed'/>

在Windows XP上启动服务器

Python twistd.py punjab 2012-01-26 10:41:45 + 0530 [ - ]日志打开。 2012-01-26 10:41:45 + 0530 [ - ] twistd 11.1.0(C:\Python27\python.exe 2.7.2)starti ng up。 2012-01-26 10:41:45 + 0530 [ - ]反应堆类:twisted.internet.selectreactor.Selec tReactor。 2012-01-26 10:41:45 + 0530 [ - ]网站开始于5280 2012-01-26 10:41:45 + 0530 [ - ]开始工厂< twisted.web。 server.Site instance at 0x013A12B0>

当我点击 http:// localhost :5280 / http-bind 我正在获得 XEP-0124 - BOSH

输入网址

http:// localhost / strophejs / facebook-chat-example / facebook .html

facebook.html / p>

< html> < head> < script src =connect.facebook/en_US/all.jstype =text / javascript>< / script> < script src =ajax.googleapis/ajax/libs/jquery/1.7.1/jquery.min.jstype =text / javascript>< / script> < script src =strophe.min.jstype =text / javascript>< / script> < script src =facebook.jstype =text / javascript>< / script> < script> var BOSH_SERVICE ='http:// localhost:5280 / http-bind' var connection = null; 函数日志(msg) { $('#log')。append('< div>< / div>')append(document.createTextNode (MSG)); } 函数rawInput(data) { log('RECV:'+ data); } 函数rawOutput(data) { log('SENT:'+ data); } function onConnect(status) { if(status == Strophe.Status.CONNECTING){ log('Strophe正在连接。 ); } else if(status == Strophe.Status.CONNFAIL){ log('Strophe failed to connect。'); $('#connect')。get(0).value ='connect'; } else if(status == Strophe.Status.DISCONNECTING){ log('Strophe is disconnecting。'); } else if(status == Strophe.Status.DISCONNECTED){ log('Strophe is disconnected。'); $('#connect')。get(0).value ='connect'; } else if(status == Strophe.Status.CONNECTED){ log('Strophe is connected。'); connection.disconnect(); } } $(document).ready(function(){ var access_token; FB.init({ appId :'XXXXXXXXXXX', status:true, cookie:true, xfbml:true, oauth:true,}); FB.login(function(response){ console.log(response); if(response.authResponse){ access_token = response.authResponse.accessToken; console .log(access_token); } else { alert('User is logged out'); } },{scope:'email,user_online_presence,friends_online_presence,xmpp_login' }); connection = new Strophe.Connection(BOSH_SERVICE); connection.rawInput = rawInput; connection.rawOutput = rawOutput; $ ('#connect')。bind('click',function(){ var button = $('#connect')。get(0); if (button.value =='connect'){ button.value ='disconnect'; connection.facebookConnect($('#jid')。get(0).value, onConnect, 300, 1,' XXXXXXXXXX',/ * app id * / 'XXXXXXXXXXXXXXXXXX',/ * secret key * / access_token); } else { button.value ='connect'; connection.disconnect(); } }); }); < / script> < / head> < body> < div id =fb-root>< / div> < div id ='login'style ='text-align:center'> < form name ='cred'> < label for ='jid'> JID:< / label> < input type ='text'id ='jid'> < label for ='pass'>密码:< / label> < input type ='password'id ='pass'> < input type ='button'id ='connect'value ='connect'> < / form> < / div> < hr> < div id ='log'>< / div> < / body> < / html>

facebook.js

/ * @author:Ruben J Garcia< rubenjgarciab@gmail& @version:1.0 本程序按照MIT许可证的条款分发。 有关详细信息,请参阅LICENSE文件。 版权所有2006-2008,OGG,LLC * / / ** *通过字符串拆分字符串 * @param分隔符字符串边界字符串。 * @param string string输入字符串。 * @param limit int [可选]如果limit设置为正,返回的数组将包含 *最大限制元素,最后 *元素包含其余字符串。 * *如果limit参数为负,则返回除最后一个限制之外的所有组件 *。 * *如果limit参数为零,则将其视为1. * * @returns数组如果分隔符为空字符串(),则 * explode将返回false。 *如果分隔符包含字符串中不包含 *的值,并使用负 *限制,则返回一个空数组 *。对于任何其他限制,将返回包含 *字符串的数组。 * / 函数explode(delimiter,string,limit){ var emptyArray = {0:''}; //不需要第三个参数 if(arguments.length< 2 || typeof arguments [0] =='undefined'|| typeof arguments [1] =='undefined'){ return null; } if(delimiter ===''|| delimiter === false || delimiter === null){ return false; } if(typeof delimiter =='function'|| typeof delimiter =='object'|| typeof string =='function'|| typeof string == 'object'){ return emptyArray; } if(delimiter === true){ delimiter ='1'; } if(!limit){ return string.toString()。split(delimiter.toString()); } else { //支持限制参数 var splitted = string.toString()。split(delimiter.toString()); var partA = splitting.splice(0,limit-1); var partB = splitted.join(delimiter.toString()); partA.push(partB); return partA; } }; / ** * X-FACEBOOK-PLATFORM SASL身份验证的处理程序。 * * @param(XMLElement)elem - 挑战节。 * * @returns false以删除处理程序。 * / Strophe.Connection.prototype._sasl_challenge1_fb = function(elem) { var challenge = Base64.decode(Strophe.getText(elem)); var nonce =; var method =; var version =; //删除不需要的处理程序 this.deleteHandler(this._sasl_failure_handler); var challenges = explode(&,challenge); (i = 0; i< challenges.length; i ++) { map = explode(=,挑战[i]); switch(map [0]) { casenonce: nonce = map [1]; break; casemethod: method = map [1]; break; caseversion: version = map [1]; break; } } var responseText =; responseText + ='api_key ='+ this.apiKey; responseText + ='& call_id ='+(Math.floor(new Date()。getTime()/ 1000)); responseText + ='& method ='+ method; responseText + ='& nonce ='+ nonce; responseText + ='& access_token ='+ this.sessionKey; responseText + ='& v ='+'1.0'; responseText + ='& sig ='+ MD5.hexdigest(responseText.replace(/& / g,)+ this.secretKey); this._sasl_challenge_handler = this._addSysHandler( this._sasl_challenge2_cb.bind(this),null,challenge,null,null); this._sasl_success_handler = this._addSysHandler( this._sasl_success_cb.bind(this),null,success,null,null); this._sasl_failure_handler = this._addSysHandler( this._sasl_failure_cb.bind(this),null,failure,null,null); this.send($ build('response',{ xmlns:Strophe.NS.SASL })。t(Base64.encode(responseText))。tree )); 返回false; }; / ** *使用Facebokk初始连接请求的处理程序。 * *此处理程序用于处理来自BOSH服务器的初始连接请求 *响应。它用于设置身份验证 *处理程序并启动身份验证过程。 * *如果可用,将尝试SASL身份验证,否则 *代码将返回到遗留身份验证。 * * @param(Strophe.Request)req - 当前请求。 * / Strophe.Connection.prototype._connect_fb = function(req){ Strophe.info(_ connect_fb被调用); this.connected = true; var bodyWrap = req.getResponse(); if(!bodyWrap){return; } this.xmlInput(bodyWrap); this.rawInput(Strophe.serialize(bodyWrap)); var typ = bodyWrap.getAttribute(type); var cond,conflict; if(typ!== null&& typ ==terminate){ //发生错误 cond = bodyWrap.getAttribute(condition); conflict = bodyWrap.getElementsByTagName(conflict); if(cond!== null){ if(cond ==remote-stream-error&& conflict.length> 0){ cond =conflict ; } this._changeConnectStatus(Strophe.Status.CONNFAIL,cond); } else { this._changeConnectStatus(Strophe.Status.CONNFAIL,unknown); } return; } //检查确保我们不覆盖这些,如果_connect_fb是 //在丢失流的情况下多次调用:features if (!this.sid){ this.sid = bodyWrap.getAttribute(sid); } if(!this.stream_id){ this.stream_id = bodyWrap.getAttribute(authid); } var wind = bodyWrap.getAttribute('requests'); if(wind){this.window = wind; } var hold = bodyWrap.getAttribute('hold'); if(hold){this.hold = hold; } var wait = bodyWrap.getAttribute('wait'); if(wait){this.wait = wait; } var mechanisms = bodyWrap.getElementsByTagName(mechanism); var i,mech,auth_str,hashed_auth_str,xfacebook; if(mechanisms.length == 0){ //我们没有获取流:功能,所以我们需要等待它 //通过发送一个空白的轮询请求 var body = this._buildBody(); this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this) .prependArg(this._connect_cb.bind这个)), body.tree()。​​getAttribute(rid))); this._throttledRequestHandler(); 返回; } else { for(i = 0; i< mechanisms.length; i ++){ mech = Strophe.getText(mechanisms [i]); if(mech =='X-FACEBOOK-PLATFORM'){ xfacebook = true; break; } } } 如果(!xfacebook){ return; } this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null); this._sasl_challenge_handler = this._addSysHandler( this._sasl_challenge1_fb.bind(this),null,challenge,null,null); this._sasl_failure_handler = this._addSysHandler( this._sasl_challenge1_fb.bind(this),null,failure,null,null); this.send($ build(auth,{ xmlns:Strophe.NS.SASL,机制:X-FACEBOOK-PLATFORM} )。树()); }; / ** *启动与Facebok XMPP Chat Server的连接过程。 * *随着连接过程的进行,用户提供的回调将使$状态更新触发多次 *。回调 *应该有两个参数 - 状态代码和错误条件。 * *状态代码将是Strophe.Status *常量中的值之一。错误条件将是RFC 3920中定义的条件 *或条件strophe-parsererror之一。 * *请参阅XEP 124以获取更详细的可选 *参数的说明。 * * @param(String)jid - 用户的JID。它必须是facebookid@chat.facebook, *其中facebook id是Facebook个人资料的编号id * @param(Function)回调connect回调函数。 * @param(Integer)wait - 可选的HTTPBIND等待值。这是 *服务器等待的时间,然后返回 *请求的空结果。建议默认设置为60秒。 *其他设置将需要调整Strophe.TIMEOUT值。 * @param(Integer)hold - 可选的HTTPBIND保持值。这是一次服务器将持有的 *连接数。这个 *应该几乎总是设置为1(默认值)。 * @param apiKey我们的Facebook应用程序的API密钥 * @param secretKey我们的Facebook应用程序的秘密密钥 * @param sessionKey我们试图使用的用户的实际会话密钥登录 * / Strophe.Connection.prototype.facebookConnect = function(jid,callback,wait,hold,apiKey,secretKey,sessionKey){ this.jid = jid; this.connect_callback = callback; this.disconnecting = false; this.connected = false; this.authenticated = false; this.errors = 0; this.apiKey = apiKey; this.secretKey = secretKey; this.sessionKey = sessionKey; this.wait = wait || this.wait; this.hold = hold || this.hold; //解析域和资源的jid this.domain = Strophe.getDomainFromJid(this.jid); //构建body标签 var body = this._buildBody()。attrs({ to:this.domain,xml:lang: en, wait:this.wait, hold:this.hold, content:text / xml; charset = utf-8, ver:1.6 ,xmpp:version:1.0,xmlns:xmpp:Strophe.NS.BOSH }); this._changeConnectStatus(Strophe.Status.CONNECTING,null); this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind( this,this._connect_fb.bind (this)), body.tree()。​​getAttribute(rid))); this._throttledRequestHandler(); };

请有人建议我正确的方式整合Facebook聊天

解决方案

这是一个非常古老的问题,但我只是遇到同样的问题,并发布这个以防万一遇到同样的问题。

我没有安装 pyopenssl ,并安装它立即修复问题。

i am trying to integrate Facebook Chat on my jQuery Mobile and considering following

But when i turn on the server ( punjab ) , and put the following necessary credential in javascript related to facebook i am getting remote-connection-failed error can anyone tell me whats missing.

JID : XXX@chat.facebook PASSWORD: <FacebookPassword>

outgoing & incoming Request

SENT:<body rid='1283282620' xmlns='jabber/protocol/httpbind' to='chat.facebook' xml:lang='en' wait='300' hold='1' content='text/xml; charset=utf-8' ver='1.6' xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh'/> RECV:<body xmlns='jabber/protocol/httpbind' type='terminate' condition='remote-connection-failed'/>

Start Server on windows XP

Python twistd.py punjab 2012-01-26 10:41:45+0530 [-] Log opened. 2012-01-26 10:41:45+0530 [-] twistd 11.1.0 (C:\Python27\python.exe 2.7.2) starti ng up. 2012-01-26 10:41:45+0530 [-] reactor class: twisted.internet.selectreactor.Selec tReactor. 2012-01-26 10:41:45+0530 [-] Site starting on 5280 2012-01-26 10:41:45+0530 [-] Starting factory <twisted.web.server.Site instance at 0x013A12B0>

When i hit localhost:5280/http-bind I am getting XEP-0124 - BOSH

Entry Url

localhost/strophejs/facebook-chat-example/facebook.html

facebook.html

<html> <head> <script src="connect.facebook/en_US/all.js" type="text/javascript"></script> <script src="ajax.googleapis/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> <script src="strophe.min.js" type="text/javascript"></script> <script src="facebook.js" type="text/javascript"></script> <script> var BOSH_SERVICE = 'localhost:5280/http-bind' var connection = null; function log(msg) { $('#log').append('<div></div>').append(document.createTextNode(msg)); } function rawInput(data) { log('RECV: ' + data); } function rawOutput(data) { log('SENT: ' + data); } function onConnect(status) { if (status == Strophe.Status.CONNECTING) { log('Strophe is connecting.'); } else if (status == Strophe.Status.CONNFAIL) { log('Strophe failed to connect.'); $('#connect').get(0).value = 'connect'; } else if (status == Strophe.Status.DISCONNECTING) { log('Strophe is disconnecting.'); } else if (status == Strophe.Status.DISCONNECTED) { log('Strophe is disconnected.'); $('#connect').get(0).value = 'connect'; } else if (status == Strophe.Status.CONNECTED) { log('Strophe is connected.'); connection.disconnect(); } } $(document).ready(function () { var access_token; FB.init({ appId : 'XXXXXXXXXXX', status : true, cookie : true, xfbml : true, oauth : true, }); FB.login(function (response) { console.log(response); if (response.authResponse) { access_token = response.authResponse.accessToken; console.log(access_token); } else { alert('User is logged out'); } },{scope: 'email,user_online_presence,friends_online_presence,xmpp_login'}); connection = new Strophe.Connection(BOSH_SERVICE); connection.rawInput = rawInput; connection.rawOutput = rawOutput; $('#connect').bind('click', function () { var button = $('#connect').get(0); if (button.value == 'connect') { button.value = 'disconnect'; connection.facebookConnect($('#jid').get(0).value, onConnect, 300, 1, 'XXXXXXXXXX' , /*app id*/ 'XXXXXXXXXXXXXXXXXX',/*secret key*/ access_token); } else { button.value = 'connect'; connection.disconnect(); } }); }); </script> </head> <body> <div id="fb-root"></div> <div id='login' style='text-align: center'> <form name='cred'> <label for='jid'>JID:</label> <input type='text' id='jid'> <label for='pass'>Password:</label> <input type='password' id='pass'> <input type='button' id='connect' value='connect'> </form> </div> <hr> <div id='log'></div> </body> </html>

facebook.js

/* @author: Ruben J Garcia <rubenjgarciab@gmail> @version: 1.0 This program is distributed under the terms of the MIT license. Please see the LICENSE file for details. Copyright 2006-2008, OGG, LLC */ /** * Split a string by string * @param delimiter string The boundary string. * @param string string The input string. * @param limit int[optional] If limit is set and positive, the returned array will contain * a maximum of limit elements with the last * element containing the rest of string. * * If the limit parameter is negative, all components * except the last -limit are returned. * * If the limit parameter is zero, then this is treated as 1. * * @returns array If delimiter is an empty string (""), * explode will return false. * If delimiter contains a value that is not * contained in string and a negative * limit is used, then an empty array will be * returned. For any other limit, an array containing * string will be returned. */ function explode(delimiter, string, limit) { var emptyArray = { 0: '' }; // third argument is not required if ( arguments.length < 2 || typeof arguments[0] == 'undefined' || typeof arguments[1] == 'undefined' ) { return null; } if ( delimiter === '' || delimiter === false || delimiter === null ) { return false; } if ( typeof delimiter == 'function' || typeof delimiter == 'object' || typeof string == 'function' || typeof string == 'object' ) { return emptyArray; } if ( delimiter === true ) { delimiter = '1'; } if (!limit) { return string.toString().split(delimiter.toString()); } else { // support for limit argument var splitted = string.toString().split(delimiter.toString()); var partA = splitted.splice(0, limit - 1); var partB = splitted.join(delimiter.toString()); partA.push(partB); return partA; } }; /** * Handler for X-FACEBOOK-PLATFORM SASL authentication. * * @param (XMLElement) elem - The challenge stanza. * * @returns false to remove the handler. */ Strophe.Connection.prototype._sasl_challenge1_fb = function (elem) { var challenge = Base64.decode(Strophe.getText(elem)); var nonce = ""; var method = ""; var version = ""; // remove unneeded handlers this.deleteHandler(this._sasl_failure_handler); var challenges = explode("&", challenge); for(i=0; i<challenges.length; i++) { map = explode("=", challenges[i]); switch (map[0]) { case "nonce": nonce = map[1]; break; case "method": method = map[1]; break; case "version": version = map[1]; break; } } var responseText = ""; responseText += 'api_key=' + this.apiKey; responseText += '&call_id=' + (Math.floor(new Date().getTime()/1000)); responseText += '&method=' + method; responseText += '&nonce=' + nonce; responseText += '&access_token=' + this.sessionKey; responseText += '&v=' + '1.0'; responseText += '&sig=' + MD5.hexdigest(responseText.replace(/&/g,"")+this.secretKey); this._sasl_challenge_handler = this._addSysHandler( this._sasl_challenge2_cb.bind(this), null, "challenge", null, null); this._sasl_success_handler = this._addSysHandler( this._sasl_success_cb.bind(this), null, "success", null, null); this._sasl_failure_handler = this._addSysHandler( this._sasl_failure_cb.bind(this), null, "failure", null, null); this.send($build('response', { xmlns: Strophe.NS.SASL }).t(Base64.encode(responseText)).tree()); return false; }; /** * Handler for initial connection request with Facebokk. * * This handler is used to process the initial connection request * response from the BOSH server. It is used to set up authentication * handlers and start the authentication process. * * SASL authentication will be attempted if available, otherwise * the code will fall back to legacy authentication. * * @param (Strophe.Request) req - The current request. */ Strophe.Connection.prototype._connect_fb = function (req) { Strophe.info("_connect_fb was called"); this.connected = true; var bodyWrap = req.getResponse(); if (!bodyWrap) { return; } this.xmlInput(bodyWrap); this.rawInput(Strophe.serialize(bodyWrap)); var typ = bodyWrap.getAttribute("type"); var cond, conflict; if (typ !== null && typ == "terminate") { // an error occurred cond = bodyWrap.getAttribute("condition"); conflict = bodyWrap.getElementsByTagName("conflict"); if (cond !== null) { if (cond == "remote-stream-error" && conflict.length > 0) { cond = "conflict"; } this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); } else { this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); } return; } // check to make sure we don't overwrite these if _connect_fb is // called multiple times in the case of missing stream:features if (!this.sid) { this.sid = bodyWrap.getAttribute("sid"); } if (!this.stream_id) { this.stream_id = bodyWrap.getAttribute("authid"); } var wind = bodyWrap.getAttribute('requests'); if (wind) { this.window = wind; } var hold = bodyWrap.getAttribute('hold'); if (hold) { this.hold = hold; } var wait = bodyWrap.getAttribute('wait'); if (wait) { this.wait = wait; } var mechanisms = bodyWrap.getElementsByTagName("mechanism"); var i, mech, auth_str, hashed_auth_str, xfacebook; if (mechanisms.length == 0) { // we didn't get stream:features yet, so we need wait for it // by sending a blank poll request var body = this._buildBody(); this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this) .prependArg(this._connect_cb.bind(this)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); return; } else { for (i = 0; i < mechanisms.length; i++) { mech = Strophe.getText(mechanisms[i]); if (mech == 'X-FACEBOOK-PLATFORM') { xfacebook = true; break; } } } if (!xfacebook) { return; } this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); this._sasl_challenge_handler = this._addSysHandler( this._sasl_challenge1_fb.bind(this), null, "challenge", null, null); this._sasl_failure_handler = this._addSysHandler( this._sasl_challenge1_fb.bind(this), null, "failure", null, null); this.send($build("auth", { xmlns: Strophe.NS.SASL, mechanism: "X-FACEBOOK-PLATFORM" }).tree()); }; /** * Starts the connection process with facebok XMPP Chat Server. * * As the connection process proceeds, the user supplied callback will * be triggered multiple times with status updates. The callback * should take two arguments - the status code and the error condition. * * The status code will be one of the values in the Strophe.Status * constants. The error condition will be one of the conditions * defined in RFC 3920 or the condition 'strophe-parsererror'. * * Please see XEP 124 for a more detailed explanation of the optional * parameters below. * * @param (String) jid - The user's JID. It must be facebookid@chat.facebook, * where facebook id is the number id of the facebook profile * @param (Function) callback The connect callback function. * @param (Integer) wait - The optional HTTPBIND wait value. This is the * time the server will wait before returning an empty result for * a request. The default setting of 60 seconds is recommended. * Other settings will require tweaks to the Strophe.TIMEOUT value. * @param (Integer) hold - The optional HTTPBIND hold value. This is the * number of connections the server will hold at one time. This * should almost always be set to 1 (the default). * @param apiKey The API key of our Facebook Application * @param secretKey The secret key of our Facebook Application * @param sessionKey The actual session key for the user who we are attempting to log in */ Strophe.Connection.prototype.facebookConnect = function (jid, callback, wait, hold, apiKey, secretKey, sessionKey){ this.jid = jid; this.connect_callback = callback; this.disconnecting = false; this.connected = false; this.authenticated = false; this.errors = 0; this.apiKey = apiKey; this.secretKey = secretKey; this.sessionKey = sessionKey; this.wait = wait || this.wait; this.hold = hold || this.hold; // parse jid for domain and resource this.domain = Strophe.getDomainFromJid(this.jid); // build the body tag var body = this._buildBody().attrs({ to: this.domain, "xml:lang": "en", wait: this.wait, hold: this.hold, content: "text/xml; charset=utf-8", ver: "1.6", "xmpp:version": "1.0", "xmlns:xmpp": Strophe.NS.BOSH }); this._changeConnectStatus(Strophe.Status.CONNECTING, null); this._requests.push( new Strophe.Request(body.tree(), this._onRequestStateChange.bind( this, this._connect_fb.bind(this)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); };

Please Someone suggest me the proper way to integrate Facebook Chat

解决方案

It's a really old question, but I just faced the same problem and posting this in case anyone faces the same problem.

I had not installed pyopenssl, and installing it fixed the problem immediately.

更多推荐

远程连接失败,与Facebook聊天连接

本文发布于:2023-10-18 05:57:10,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1503332.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Facebook

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!