gpt4 book ai didi

java - 套接字流的 flush() 有多可靠?

转载 作者:可可西里 更新时间:2023-11-01 02:33:36 26 4
gpt4 key购买 nike

考虑这段(简化的)代码:

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com