- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在使用 Jean-Rodolphe Letertre 为 app inventor 2 开发的 tcp 客户端扩展,它可以完美运行,直到您调用 disconnect 方法并导致应用程序崩溃。在查看扩展代码后,我发现断开连接只会关闭输出、输入,而不是关闭不会导致任何崩溃的套接字,所以我怀疑运行线程的连接方法,因为它一直在循环中读取数据来自 tcp 套接字,当我们调用断开连接时,我们没有完成导致应用程序崩溃的线程,因为输入已关闭并且未处理异常。
注意:代码不是我的,我不要求为我修复它,我只想知道我是否找到了导致崩溃的问题,如果是,我会修复它我。在此先感谢您的帮助!
代码:
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.gmail.at.moicjarod;
import com.google.appinventor.components.runtime.*;
import com.google.appinventor.components.runtime.util.RuntimeErrorAlert;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesLibraries;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.runtime.util.AsynchUtil;
import com.google.appinventor.components.runtime.util.ErrorMessages;
import com.google.appinventor.components.runtime.util.YailList;
import com.google.appinventor.components.runtime.util.SdkLevel;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import android.os.StrictMode;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* Simple Client Socket
* @author moicjarod@gmail.com (Jean-Rodolphe Letertre)
* with the help of the work of lizlooney @ google.com (Liz Looney) and josmasflores @ gmail.com (Jose Dominguez)
* the help of Alexey Brylevskiy for debugging
* and the help of Hossein Amerkashi from AppyBuilder for compatibility with AppyBuilder
*/
@DesignerComponent(version = 4,
description = "Non-visible component that provides client socket connectivity.",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "http://jr.letertre.free.fr/Projets/AIClientSocket/clientsocket.png")
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.INTERNET")
public class ClientSocketAI2Ext extends AndroidNonvisibleComponent implements Component
{
private static final String LOG_TAG = "ClientSocketAI2Ext";
private final Activity activity;
// the socket object
private Socket clientSocket = null;
// the address to connect to
private String serverAddress = "";
// the port to connect to
private String serverPort = "";
// boolean that indicates the state of the connection, true = connected, false = not connected
private boolean connectionState = false;
// boolean that indicates the mode used, false = string sent as is, true = String is considered as hexadecimal data and will be converted before sending
// same behavior is used when receiving data
private boolean hexaStringMode = false;
InputStream inputStream = null;
/**
* Creates a new Client Socket component.
*
* @param container the Form that this component is contained in.
*/
public ClientSocketAI2Ext(ComponentContainer container)
{
super(container.$form());
activity = container.$context();
// compatibility with AppyBuilder (thx Hossein Amerkashi <kkashi01 [at] gmail [dot] com>)
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
/**
* Method that returns the server's address.
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = "The address of the server the client will connect to.")
public String ServerAddress()
{
return serverAddress;
}
/**
* Method to specify the server's address
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING)
@SimpleProperty
public void ServerAddress(String address)
{
serverAddress = address;
}
/**
* Method that returns the server's port.
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = "The port of the server the client will connect to.")
public String ServerPort()
{
return serverPort;
}
/**
* Method to specify the server's port
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING)
@SimpleProperty
public void ServerPort(String port)
{
serverPort = port;
}
/**
* Method that returns the connection state
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = "The state of the connection - true = connected, false = disconnected")
public boolean ConnectionState()
{
return connectionState;
}
/**
* Method that returns the mode (string or hexastring)
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = "The mode of sending and receiving data.")
public boolean HexaStringMode()
{
return hexaStringMode;
}
/**
* Method to specify the mode (string or hexastring)
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN)
@SimpleProperty
public void HexaStringMode(boolean mode)
{
hexaStringMode = mode;
}
/**
* Creates the socket, connect to the server and launches the thread to receive data from server
*/
@SimpleFunction(description = "Tries to connect to the server and launches the thread for receiving data (blocking until connected or failed)")
public void Connect()
{
if (connectionState == true)
{
throw new YailRuntimeError("Connect error, socket connected yet, please disconnect before reconnect !", "Error");
}
try
{
// connecting the socket
clientSocket = new Socket();
clientSocket.connect(new InetSocketAddress(serverAddress, Integer.parseInt(serverPort)), 5000);
connectionState = true;
// begin the receive loop in a new thread
AsynchUtil.runAsynchronously(new Runnable()
{
@Override
public void run()
{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
try
{
// get the input stream and save the data
inputStream = clientSocket.getInputStream();
while (true)
{
// test if there is a server problem then close socket properly (thx Axeley :-))
try
{
bytesRead = inputStream.read(buffer);
if(bytesRead == -1)
break;
}
catch(SocketException e)
{
if(e.getMessage().indexOf("ETIMEDOUT") >= 0)
break;
throw e;
}
byteArrayOutputStream.write(buffer, 0, bytesRead);
final String dataReceived;
// hexaStringMode is false, so we don't transform the string received
if (hexaStringMode == false)
{
dataReceived = byteArrayOutputStream.toString("UTF-8");
}
// hexaStringMode is true, so we make a string with each character as an hexa symbol representing the received message
else
{
int i;
char hexaSymbol1, hexaSymbol2;
String tempData = "";
byte[] byteArray = byteArrayOutputStream.toByteArray();
for (i = 0; i < byteArrayOutputStream.size(); i++)
{
if (((byteArray[i] & 0xF0) >> 4) < 0xA)
// 0 to 9 symbol
hexaSymbol1 = (char)(((byteArray[i] & 0xF0) >> 4) + 0x30);
else
// A to F symbol
hexaSymbol1 = (char)(((byteArray[i] & 0xF0) >> 4) + 0x37);
if ((byteArray[i] & 0x0F) < 0xA)
hexaSymbol2 = (char)((byteArray[i] & 0x0F) + 0x30);
else
hexaSymbol2 = (char)((byteArray[i] & 0x0F) + 0x37);
tempData = tempData + hexaSymbol1 + hexaSymbol2;
}
dataReceived = tempData;
}
// reset of the byteArrayOutputStream to flush the content
byteArrayOutputStream.reset();
// then we send the data to the user using an event
// events must be sent by the main thread (UI)
activity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
DataReceived(dataReceived);
}
} );
}
// When we go there, either we have
// - server shutdown
// - disconnection asked (inputstream closed => -1 returned)
// - connection problem
// so, if it is not disconnected yet, we disconnect the socket and inform the user of it.
if (connectionState == true)
{
Disconnect();
// events must be sent by the main thread (UI)
activity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
RemoteConnectionClosed();
}
} );
}
}
catch (SocketException e)
{
Log.e(LOG_TAG, "ERROR_READ", e);
throw new YailRuntimeError("Connect error (read)" + e.getMessage(), "Error");
}
catch (IOException e)
{
Log.e(LOG_TAG, "ERROR_READ", e);
throw new YailRuntimeError("Connect error (read)", "Error");
}
catch (Exception e)
{
connectionState = false;
Log.e(LOG_TAG, "ERROR_READ", e);
throw new YailRuntimeError("Connect error (read)" + e.getMessage(), "Error");
}
}
} );
}
catch (SocketException e)
{
Log.e(LOG_TAG, "ERROR_CONNECT", e);
throw new YailRuntimeError("Connect error" + e.getMessage(), "Error");
}
catch (Exception e)
{
connectionState = false;
Log.e(LOG_TAG, "ERROR_CONNECT", e);
throw new YailRuntimeError("Connect error (Socket Creation)" + e.getMessage(), "Error");
}
}
/**
* Send data through the socket to the server
*/
@SimpleFunction(description = "Send data to the server")
public void SendData(final String data)
{
final byte [] dataToSend;
byte [] dataCopy = data.getBytes();
if (connectionState == false)
{
throw new YailRuntimeError("Send error, socket not connected.", "Error");
}
if (hexaStringMode == false)
{
//dataSend = new byte [data.length()];
// if hexaStringMode is false, we send data as is
dataToSend = data.getBytes();
}
else
{
// if hexaStringMode is true, we begin to verify we can transcode the symbols
// verify if the data we want to send contains only hexa symbols
int i;
for (i = 0; i < data.length(); i++)
{
if (((dataCopy[i] < 0x30) || (dataCopy[i] > 0x39)) && ((dataCopy[i] < 0x41) || (dataCopy[i] > 0x46)) && ((dataCopy[i] < 0x61) || (dataCopy[i] > 0x66)))
throw new YailRuntimeError("Send data : hexaStringMode is selected and non hexa symbol found in send String.", "Error");
}
// verify that the number of symbols is even
if ((data.length() %2) == 1)
{
throw new YailRuntimeError("Send data : hexaStringMode is selected and send String length is odd. Even number of characters needed.", "Error");
}
// if all tests pass, we transcode the data :
dataToSend=new byte[data.length()/2+1];
for (i = 0; i < data.length(); i=i+2)
{
byte [] temp1 = new byte [2];
temp1 [0] = dataCopy[i];
temp1 [1] = dataCopy[i+1];
String temp2 = new String (temp1);
dataToSend[i/2]=(byte)Integer.parseInt(temp2, 16);
}
// end of c-type string character
dataToSend[i/2] = (byte)0x00;
}
// we then send asynchonously the data
AsynchUtil.runAsynchronously(new Runnable()
{
@Override
public void run()
{
try
{
OutputStream out;
out = clientSocket.getOutputStream();
out.write(dataToSend);
}
catch (SocketException e)
{
Log.e(LOG_TAG, "ERROR_SEND", e);
throw new YailRuntimeError("Send data" + e.getMessage(), "Error");
}
catch (Exception e)
{
Log.e(LOG_TAG, "ERROR_UNABLE_TO_SEND_DATA", e);
throw new YailRuntimeError("Send Data", "Error");
}
}
} );
}
/**
* Close the socket
*/
@SimpleFunction(description = "Disconnect to the server")
public void Disconnect()
{
if (connectionState == true)
{
connectionState = false;
try
{
// shutdown the input socket,
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
clientSocket.close();
}
catch (SocketException e)
{
// modifications by axeley too :-)
if(e.getMessage().indexOf("ENOTCONN") == -1)
{
Log.e(LOG_TAG, "ERROR_CONNECT", e);
throw new YailRuntimeError("Disconnect" + e.getMessage(), "Error");
}
// if not connected, then just ignore the exception
}
catch (IOException e)
{
Log.e(LOG_TAG, "ERROR_CONNECT", e);
throw new YailRuntimeError("Disconnect" + e.getMessage(), "Error");
}
catch (Exception e)
{
Log.e(LOG_TAG, "ERROR_CONNECT", e);
throw new YailRuntimeError("Disconnect" + e.getMessage(), "Error");
}
finally
{
clientSocket=null;
}
}
else
throw new YailRuntimeError("Socket not connected, can't disconnect.", "Error");
}
/**
* Event indicating that a message has been received
*
* @param data the data sent by the server
*/
@SimpleEvent
public void DataReceived(String data)
{
// invoke the application's "DataReceived" event handler.
EventDispatcher.dispatchEvent(this, "DataReceived", data);
}
/**
* Event indicating that the remote socket closed the connection
*
*/
@SimpleEvent
public void RemoteConnectionClosed()
{
// invoke the application's "RemoteConnectionClosed" event handler.
EventDispatcher.dispatchEvent(this, "RemoteConnectionClosed");
}
}
最佳答案
通过注释以下行,可以实现:
throw new YailRuntimeError("...
这种方法的问题是我们无法知道断开连接的原因,但是我们必须同意这些消息在应用程序工作流的意义上比功能更重要,因此另一种选择是添加在运行时禁用这些调用的能力。
关于java - AppInventor2 TCP 客户端扩展使应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54130233/
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我的第一个想法如下: 我在服务器上创建了一个中央 ServerSocket,所有应用程序都可以连接到该服务器。
我正在 Unity 中构建多人游戏。为此,我必须将一些值从客户端发送到两个或多个通过服务器连接的客户端。我想将其构建为服务器真实游戏。客户端将使用 Android,他们的数据将通过服务器同步(可能是一
练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消
我使用证书身份验证设置了 AWS Client VPN。我正在为客户端-客户端访问系统进行设置,基本上如 this AWS scenario/example 中所述.一切正常,如果我知道他们的 IP
我正在开发一个小型客户端1/客户端2、服务器(线程)TCP 游戏。在尝试处理延迟问题时,我意识到我的 transmitState() 中存在缺陷。它强制将不必要的信息传递到通讯流中,从而造成迟缓,将汽
来自文档:Configurable token lifetimes in Azure Active Directory (Public Preview) 它提到“ secret 客户端”,刷新 tok
Apollo 客户端开发工具无法连接到我的应用程序。我已在 ApolloClient 构造函数中将 connectToDevTools 传递为 true,但没有任何 react 。我也试过this p
我想在 Pod 内使用 Fabric8 kubernetes 客户端 (java)。如何获取部署集群的 kubernetes 客户端? 我可以使用该集群的 kubeconfig 文件获取任何集群的配置
我正在阅读 the security issue with Log4j我了解此产品受此漏洞影响。但是 Oracle 客户端 11.2 和 12 是否受此问题影响? 我找不到这些产品是否使用任何 Log
Eureka 服务器设置 pom.xml 1.8 Hoxton.SR1 org.springframework.cloud spring
我有一个点对点(客户端/服务器)设置(通过本地 LAN),它使用 Netty,一个 Java 网络框架。我使用原始 TCP/IP(例如,没有 HTTP)进行通信和传输。现在,根据要求,我们希望转向 T
上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。 但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。 接下来要做的就是实现Modb
有没有办法将二维十六进制代码数组转换为 png 图像? 数组看起来像这样(只是更大) [ [ '#FF0000', '#00FF00' ], [ '#0000FF'
我是套接字编程的新手。每次我运行客户端程序时,它都会说“无法连接到服务器”。谁能告诉我我在哪里犯了错误。任何帮助将不胜感激。 这是client.c #include #include #inclu
我们在UNIX环境下制作了简单的client.c和server.c程序。我们使用它来传输一个简单的文本文件,首先打开它,然后读取它并使用 open、read 和 send 系统调用发送;在客户端,我接
当我的程序来自 my previous question正在响应客户端,它应该发送加密消息。 当客户端连接时,它会发送一条类似“YourMessage”的消息。现在我想做的是,当客户端连接时,应该以某
我正在使用 C 和 putty 编写客户端/服务器程序。两个 c 文件位于同一系统上。 我目前在向客户端写回其正在使用的框架以及打印我的框架时遇到问题。它打印出 3 0 9 8,但随后开始打印 134
我正在使用 C 中的 select() 制作一个模拟快餐或其他任何东西的客户端服务器。 我有客户随机点 1-5 种“食物”。服务器每 30 秒决定一次。所有客户最喜欢的食物是什么?他为那些客户提供服务
对于单机游戏,基本的游戏循环是(来源:维基百科) while( user doesn't exit ) check for user input run AI move enemies
1、CentOS安装TortoiseSVN 复制代码 代码如下: yum install -y subversion 2、SVN客户端命令
我是一名优秀的程序员,十分优秀!