感谢阅读!
背景:
我正在为服务器开发一个 Android 客户端,其中要求应用程序需要与基于 WebSockets 的服务器来回连续交换消息。
实现:对于客户端,我使用weberknecht's Android 的 WebSocket 客户端库,而服务器是基于 Tornado 的。
问题:
目前,我通过生成 AsyncTask 在 onCreate 中调用 initWebSocketClient。但是,我不断收到客户端超时异常。
安卓客户端:
private void initWebSocketClient() {
Log.e(TAG, "initWebSocketClient");
try {
URI url = new URI("ws://192.168.207.84:8080/");
WebSocket websocket = new WebSocketConnection(url);
// Register Event Handlers
websocket.setEventHandler(new WebSocketEventHandler() {
public void onOpen()
{
Log.e(TAG, "--open");
}
public void onMessage(WebSocketMessage message)
{
Log.e(TAG, "--received message: " + message.getText());
}
public void onClose()
{
Log.e(TAG, "--close");
}
});
// Establish WebSocket Connection
websocket.connect();
// Send UTF-8 Text
websocket.send("hello world");
// Close WebSocket Connection
websocket.close();
}
catch (WebSocketException wse) {
wse.printStackTrace();
}
catch (URISyntaxException use) {
use.printStackTrace();
}
}
Tornado 服务器:
#!/usr/bin/env python
import tornado.ioloop
import tornado.web
import tornado.websocket
class EchoWebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print "WebSocket opened"
def on_message(self, message):
self.write_message(u"You said: " + message)
def on_close(self):
print "WebSocket closed"
application = tornado.web.Application([
(r"/", EchoWebSocketHandler),
])
if __name__ == "__main__":
application.listen(8080)
tornado.ioloop.IOLoop.instance().start()
客户端超时异常:
01-31 19:28:01.367: W/System.err(5668): de.roderick.weberknecht.WebSocketException: error while creating socket to ws://192.168.207.84:8080/
01-31 19:28:01.386: W/System.err(5668): at de.roderick.weberknecht.WebSocketConnection.createSocket(WebSocketConnection.java:244)
01-31 19:28:01.386: W/System.err(5668): at de.roderick.weberknecht.WebSocketConnection.connect(WebSocketConnection.java:83)
01-31 19:28:01.386: W/System.err(5668): at com.sagar.websockclient.MainActivity.initWebSocketClient(MainActivity.java:55)
01-31 19:28:01.390: W/System.err(5668): at com.sagar.websockclient.MainActivity.access$0(MainActivity.java:30)
01-31 19:28:01.390: W/System.err(5668): at com.sagar.websockclient.MainActivity$WebSocketTask.doInBackground(MainActivity.java:75)
01-31 19:28:01.390: W/System.err(5668): at com.sagar.websockclient.MainActivity$WebSocketTask.doInBackground(MainActivity.java:1)
01-31 19:28:01.390: W/System.err(5668): at android.os.AsyncTask$2.call(AsyncTask.java:264)
01-31 19:28:01.390: W/System.err(5668): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-31 19:28:01.390: W/System.err(5668): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-31 19:28:01.390: W/System.err(5668): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-31 19:28:01.390: W/System.err(5668): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-31 19:28:01.390: W/System.err(5668): at java.lang.Thread.run(Thread.java:856)
01-31 19:28:01.390: W/System.err(5668): Caused by: java.net.ConnectException: failed to connect to /192.168.207.84 (port 8080): connect failed: ETIMEDOUT (Connection timed out)
01-31 19:28:01.390: W/System.err(5668): at libcore.io.IoBridge.connect(IoBridge.java:114)
01-31 19:28:01.394: W/System.err(5668): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
01-31 19:28:01.394: W/System.err(5668): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
01-31 19:28:01.394: W/System.err(5668): at java.net.Socket.startupSocket(Socket.java:566)
01-31 19:28:01.394: W/System.err(5668): at java.net.Socket.tryAllAddresses(Socket.java:127)
01-31 19:28:01.394: W/System.err(5668): at java.net.Socket.(Socket.java:177)
01-31 19:28:01.394: W/System.err(5668): at java.net.Socket.(Socket.java:149)
01-31 19:28:01.394: W/System.err(5668): at de.roderick.weberknecht.WebSocketConnection.createSocket(WebSocketConnection.java:238)
01-31 19:28:01.394: W/System.err(5668): ... 11 more
01-31 19:28:01.394: W/System.err(5668): Caused by: libcore.io.ErrnoException: connect failed: ETIMEDOUT (Connection timed out)
01-31 19:28:01.398: W/System.err(5668): at libcore.io.Posix.connect(Native Method)
01-31 19:28:01.398: W/System.err(5668): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
01-31 19:28:01.398: W/System.err(5668): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
01-31 19:28:01.398: W/System.err(5668): at libcore.io.IoBridge.connect(IoBridge.java:112)
01-31 19:28:01.398: W/System.err(5668): ... 18 more
有人可以帮帮我吗?
更新:添加 AutoBahn(适用于 Android 的 WebSocket 客户端库)实现细节:
高速公路客户端
private void connect2() {
mConnection = new WebSocketConnection();
final String wsuri = "ws://192.168.0.137:8888/";
String TAG = "ArticlesListActivity";
try {
mConnection.connect(wsuri, new WebSocketHandler() {
@Override
public void onOpen() {
Log.e(TAG, "Connected to: " + wsuri);
}
@Override
public void onTextMessage(String payload) {
Log.e(TAG, "Message recieved = " + payload);
}
@Override
public void onClose(int code, String reason) {
Log.e(TAG, "Connection Lost.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
}
有了这个库——我可以连接到服务器,但连接立即断开。 (请参阅下面的“AutoBahn 客户端日志”。切换回 weberknecht 工作正常。我没有在任何地方明确调用 mConnection.disconnect()。所以我不知道连接是如何终止的。
AutoBahn 客户端日志
02-27 14:27:36.605: D/de.tavendo.autobahn.WebSocketConnection(27701): created
02-27 14:27:36.656: D/dalvikvm(27701): GC_FOR_ALLOC freed 164K, 4% free 9247K/9543K, paused 17ms
02-27 14:27:36.671: D/dalvikvm(27701): GC_FOR_ALLOC freed 7K, 4% free 9368K/9735K, paused 14ms
02-27 14:27:36.671: D/de.tavendo.autobahn.WebSocketReader(27701): created
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketConnection(27701): WS reader created and started
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketReader(27701): running
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketWriter(27701): created
02-27 14:27:36.675: D/de.tavendo.autobahn.WebSocketConnection(27701): WS writer created and started
02-27 14:27:36.769: D/de.tavendo.autobahn.WebSocketReader(27701): run() : ConnectionLost
02-27 14:27:36.773: D/de.tavendo.autobahn.WebSocketReader(27701): ended
02-27 14:27:36.777: D/de.tavendo.autobahn.WebSocketConnection(27701): opening handshake received
02-27 14:27:36.777: E/ArticlesListActivity(27701): Connected to: ws://192.168.0.137:8888/
02-27 14:27:36.781: D/de.tavendo.autobahn.WebSocketConnection(27701): fail connection [code = 3, reason = WebSockets connection lost
02-27 14:27:36.784: D/de.tavendo.autobahn.WebSocketReader(27701): quit
02-27 14:27:36.788: D/de.tavendo.autobahn.WebSocketWriter(27701): ended
02-27 14:27:36.792: E/ArticlesListActivity(27701): Connection Lost.
02-27 14:27:36.792: D/de.tavendo.autobahn.WebSocketConnection(27701): worker threads stopped
最佳答案
以下是我开始解决此问题的方法:
您是尝试在手机(设备)还是模拟器上执行此操作?如果您尝试在您的手机上执行此操作,您是通过 3G 连接的,则不会发生这种情况。在这种情况下,您正尝试从不起作用的 WAN 连接到一个内部 IP 地址。
再次假设您是在设备上执行此操作,如果您是通过 Wifi 连接的,那就是另一回事了。确保服务器可以到达 192.168.207.84:8080。一种快速测试连接性的方法(从您的 PC):
telnet 192.168.207.84 8080
如果超时,您就知道您的服务器没有响应。这当然假设您的 PC 与您的 Wifi 网络位于同一子网。
如果您尝试从您的模拟器执行此操作,请按照 [2] 中的步骤确保服务器可访问,并确保您的模拟器处于 (IP) 桥接模式。
总而言之,超时的主要原因通常是因为服务器可用性不足(即缺乏连接)。您没有提到您的网络的详细信息,所以我在这里根据您尝试连接的 IP (192.168.207.84) 做了一些假设。
关于android websocket客户端超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9089231/
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p
在Ruby中,我需要在n毫秒秒后暂停一段代码的执行。我知道RubyTimeout库支持秒的超时:http://ruby-doc.org/stdlib/libdoc/timeout/rdoc/index.html这可能吗? 最佳答案 只需为超时使用十进制值。n毫秒的示例:Timeout::timeout(n/1000.0){sleep(100)} 关于Ruby在n*milli*秒后超时一段代码,我们在StackOverflow上找到一个类似的问题: https:
我想在Ruby的TCPServer中获取客户端的IP地址。以及(如果可能的话)MAC地址。例如,Ruby中的时间服务器,请参阅评论。tcpserver=TCPServer.new("",80)iftcpserverputs"Listening"loopdosocket=tcpserver.acceptifsocketThread.newdoputs"Connectedfrom"+#HERE!HowcanigettheIPAddressfromtheclient?socket.write(Time.now.to_s)socket.closeendendendend非常感谢!
我有一个模型User,它在创建后的回调中创建了选项#Userhas_one:user_optionsafter_create:create_optionsprivatedefcreate_optionsUserOptions.create(user:self)end我对此有一些简单的Rspec覆盖:describe"newuser"doit"createsuser_optionsaftertheuseriscreated"douser=create(:user)user.user_options.shouldbe_kind_of(UserOptions)endend一切正常,直到我将自
我正在尝试使用RubyEventMachine访问使用SSL证书身份验证的HTTPSWeb服务,但我没有让它工作。我编写了以下简单代码块来对其进行端到端测试:require'rubygems'require'em-http'EventMachine.rundourl='https://foobar.com/'ssl_opts={:private_key_file=>'/tmp/private.key',:cert_chain_file=>'/tmp/ca.pem',:verify_peer=>false}http=EventMachine::HttpRequest.new(url).g
我正在为需要与API建立SSL连接的客户端开发应用程序。我得到了三个文件;一个信任根证书(.cer)文件、一个中间证书(.cer)文件和一个签名的响应文件。我得到的安装说明与IIS或Javakeytool程序有关;我正在用RubyonRails构建应用程序,所以这两种方法都不是一个选项(据我所知)。证书由运行API服务的组织自签名,看来我获得了客户端证书以相互验证https连接。我不确定如何使用我的应用程序中的证书连接和使用API签名响应文件的作用我读过"Usingaself-signedcertificate"和thisarticleonOpenSSLinRuby但两者似乎都不是很到
我正在努力在Ruby中创建启用SSL的服务器,以及与服务器一起使用的相应Ruby客户端。为了进行测试,我使用以下命令创建了自己的根CA证书。$:~/devel/ssl-test/ssl/CA$opensslgenrsa-outTestCA.key2048GeneratingRSAprivatekey,2048bitlongmodulus............+++...........................+++eis65537(0x10001)$:~/devel/ssl-test/ssl/CA$opensslreq-new-keyTestCA.key-outTestCA.
我有一个通过IMAP处理传入电子邮件的Rails应用程序。当前使用一种方法来搜索TMail对象的各个部分以查找给定的content_type:defself.search_parts_for_content_type(parts,content_type='text/html')parts.eachdo|part|ifpart.content_type==content_typereturnpart.bodyelseifpart.multipart?ifbody=self.search_parts_for_content_type(part.parts,content_type)ret
我正在尝试使用Prawn生成PDF报告,我可以通过传递单个ID轻松地让它对表演Action进行报告,但我想生成一个包含其中每条记录的报告。就像一个标准的railsscaffold索引页面。使用rails它看起来像这样:简单!但我不确定如何用Prawn做到这一点..类似于:defindex@customer=Customer.allrespond_todo|format|format.htmlPrawn::Document.generate("customer_list.pdf")do|pdf|pdf.text"#{@customer.id}"pdf.text"#{@customer.n