- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
考虑这段(简化的)代码:
public class Test {
// assigned elsewhere
InetSocketAddress socketAddress;
String socketHost;
int socketPort;
Socket socket;
int COMMAND = 10;
int CONNECTION_TIMEOUT = 10 * 1000;
int SOCKET_TIMEOUT = 30 * 1000;
DataOutputStream dos;
DataInputStream dis;
protected void connect() throws IOException, InterruptedException {
socket.connect(socketAddress != null ? socketAddress : new InetSocketAddress(socketHost, socketPort), CONNECTION_TIMEOUT);
socket.setSoTimeout(SOCKET_TIMEOUT);
socket.setTcpNoDelay(true);
}
void initializeDataStreams() throws IOException {
dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), socket.getSendBufferSize()));
dis = new DataInputStream( new BufferedInputStream( socket.getInputStream(), socket.getReceiveBufferSize()));
}
void run() {
try {
connect();
initializeDataStreams();
sendCommand(COMMAND, true);
sendIdAndUsername(true);
sendSyncPreference(true);
sendBlockedIds(true);
sendHeaders();
// reading from 'dis' here
// ...
} catch (InterruptedException | IOException e){
/* ... */
}
}
void sendCommand(int command, boolean buffered) throws IOException {
dos.write(command);
if (!buffered) {
dos.flush();
}
}
void sendIdAndUsername(boolean buffered) throws IOException {
sendId(true); // always buffered
String username = "user name";
dos.writeBoolean(username != null);
if (username != null) {
dos.writeUTF(username);
}
if (!buffered) {
dos.flush();
}
}
void sendId(boolean buffered) throws IOException {
dos.writeUTF("user id");
if (!buffered) {
dos.flush();
}
}
void sendSyncPreference(boolean buffered) throws IOException {
boolean fullSync = true;
dos.writeBoolean(fullSync);
if (!buffered) {
dos.flush();
}
}
void sendBlockedIds(boolean buffered) throws IOException {
Set<String> blockedCrocoIds = new HashSet<>();
ObjectOutputStream oos = new ObjectOutputStream(dos);
oos.writeObject(blockedCrocoIds);
if (!buffered) {
oos.flush();
}
}
private void sendHeaders() throws IOException {
dos.writeUTF("some string");
dos.writeInt(123);
// some other writes...
// this should flush everything, right?
dos.flush();
}
}
我故意将它与所有方法一起保留,以防万一我在那里犯了一些非常明显的错误。当我执行 Test.run() 时,有时(真的很难准确预测何时)似乎 sendHeaders() 中的 flush() 根本不起作用。
服务器端在接下来的 22 秒内没有在其 ServerSocket.accept() 上接收到任何信息(不要问我这个数字是从哪里来的,这是一个谜)。
我的想法是,我不会在每次传输时都调用 flush(),而是只调用一次,以节省带宽。
那么这段代码有什么问题呢?如何确保对我的流的写入是可靠的/即时的,以便服务器可以尽快读取它?
我也接受“没有问题”的回答,在那种情况下,它一定是并行完成的并且影响了 Android 上的网络堆栈。
编辑:服务器代码真的没什么特别的:
ListeningThread listeningThread = new ListeningThread();
listeningThread.start();
listeningThread.join();
然后:
public class ListeningThread extends Thread {
private ServerSocket serverSocket;
public ListeningThread() {
try {
// unbound server socket
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(NetworkUtil.APP_SERVER_PORT));
} catch (IOException e) {
log(e);
}
}
@Override
public void run() {
log("run");
while (serverSocket.isBound() && !isInterrupted()) {
try {
Socket socket = serverSocket.accept();
new CommandThread(socket).start();
} catch (IOException e) {
log(e);
}
}
try {
serverSocket.close();
} catch (IOException e) {
log(e);
}
}
}
最后:
public class CommandThread extends Thread {
private final Socket socket;
public CommandThread(Socket socket) {
log("CommandThread");
this.socket = socket;
}
@Override
public void run() {
log("run");
try {
socket.setSoTimeout(NetworkUtil.SOCKET_TIMEOUT);
socket.setTcpNoDelay(true);
InputStream is = socket.getInputStream();
int cmd = is.read(); // <========= so actually this is failing
switch (cmd) {
// handling of the command
case COMMAND:
new DownloadMessagesThread(socket).start();
break;
}
} catch (IOException | SQLException e) {
log(e);
}
}
}
正如评论中提到的,我愿意同意对象流和 co 的任何错误,但问题是我无法访问(同样,它只是有时,它非常随机......)CommandThread 的跑()。因此,除非我遗漏了其他东西,否则对象流不可能导致这种故障。
编辑 2: 更正:这不是我无法访问的 accept(),它是第一个读取操作:
03-07 11:22:42.965 00010 CommandThread: CommandThread
03-07 11:22:42.966 00108 CommandThread: run
[... nothing happening ...]
03-07 11:23:04.549 00111 DownloadMessagesThread: run
这到底是不是对象流和数据流混在一起造成的?
最佳答案
您应该验证 sendBlockedIds
中的 ObjectOutputStream
创建不是罪魁祸首。在混合 DataStreams 和 ObjectStreams 时,我已经遇到了一些协议(protocol)“死锁”,因为 ObjectStreams 的 Writer/Reader 对的创建意味着一种握手,这种握手在混合这些流时可能会失败。
编辑:在再次阅读您的问题时,我意识到我还没有回答。所以是的,它是可靠的。 EJP 回答 +1。
关于java - 套接字流的 flush() 有多可靠?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38223117/
我正在尝试运行以下内容:: Press to see code - name: Snapshot BI nodes hosts: [CLUSTER-BI,CLUSTER-BI-REPL
在这里尝试心理重置:我尝试使用 MSMQ 创建一个可靠、持久的堆栈,但没有成功 所以更一般地说: 我有生产者(一个 web 服务,虽然“只有一个”,但也是多线程的)/消费者(多个进程,根据需要设置)。
试图为分布式系统找到一个商业日志框架。此框架必须允许远程服务器上的 .NET 应用程序记录可以在中央位置收集的消息。如果可能,中央位置应将消息存储在 SQL Server 数据库中。 要求: 能够在远
我正在开发 Restful 服务,我们将在数据库中插入/更新新记录。 由于REST使用HTTP进行通信,而HTTP并不可靠,我担心如果连接失败,请求可能无法发送到服务器。 我在 link 中找到的建议
我正在尝试实现一个页面,员工可以在其中登录并添加、修改、更新工作案例。 我有一个选择列表,其中包含从数据库加载的数据(员工姓名)。在这个数据库中,我有基本信息、用户名、ID、密码、电子邮件。 选择列表
我在 C 代码和 Python 代码之间(偶尔)得到略有不同的计算结果,并设法找到了一个例子。在 Python 中,我得到了这个: >>> print "%.55f" %\ ... (-2.49999
例如如果我将计时器设置为每天午夜到期,如果一个“失火”(例如,由于服务器关闭而不会触发回调)会发生什么?我在文档中找不到它。 有没有办法让这个定时器在服务器重启时立即触发回调? PS:我了解 Quar
我有一组不同长度的非零序列,我正在使用 Keras LSTM 对这些序列建模。我使用 Keras Tokenizer 进行分词(分词从 1 开始)。为了使序列具有相同的长度,我使用了填充。 填充示例:
我遇到了一个非常有趣的可靠 session 行为。我正在使用 netTcp 绑定(bind) + 双工 channel + 可靠 session 。 当我尝试在 channel.faulted 上收听
问题: 给定表 table_a 和 table_b,每当 table_a 更新时,我都需要可靠地(并发地)执行这样的操作: SELECT table_a 中的一些行。 在应用程序代码中计算一些内容。
我们目前的设计 环境 Redis 2.8.17 我们已经实现了我们的可靠队列,使用类似于 redis 文档中描述的模式的模式,在 RPOPLPUSH 下 但是,考虑到其阻塞性质,我们正在使用 BRPO
在我们的 WCF 应用程序中,我正在尝试配置可靠的 session 。 服务: 客户:
我使用这个 Delphi 7 代码来检测 Internet Explorer 是否正在运行: function IERunning: Boolean; begin Result := FindWi
我正在准备构建一个应用程序,该应用程序能够向 GPS 设备发送/接收航路点。通过一些谷歌搜索,我发现了很多可能对此目的有用的库: Java Chaeron GPS GPSLib4J Python Py
我有几个关于 WCF 可靠 session 可靠性的问题: WCF 是否在重试期间重新序列化消息? 2。如果 1 是正确的 - 它是否在消息参数被处理后发生? 3. 如果 2 是正确的 - 是否有任何
对于使用 $(this)[0].defaultValue 来确定文本框值是否已从原始值发生变化的一些反馈,我将不胜感激,例如 //keyUp event if($(this)[0].defaultVa
我正在开发一个具有以下特征的实时应用程序: 数百个客户端将同时插入行/文档,每个客户端每隔几秒插入一行。 大部分仅追加;几乎所有的行/文档,一旦插入,就永远不会改变。 只有当数据刷新到磁盘时,客户端才
场景:最终用户(不受信任的)提供了一个字符串,例如 "Hello, {name}!" .在服务器上,我想以 my_string.format(name="Homer") 的形式对该用户提供的字符串进行
我在推送通知方面遇到一些问题。我们使用 Firebase 来推送通知。问题是我可以在一台 iPhone 上正确接收 PushNotifications,但无法在另一台 iPhone 上接收它们。我在
从 python 到 c++,这是我能得到的最接近 python 的装饰器。 这个解决方案感觉有点像 hack,因为在要装饰的函数之后运行的代码在 Timer 析构函数中是隐式调用的。不过它确实有效。
我是一名优秀的程序员,十分优秀!