java – socket流的flush()的可靠性如何?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – socket流的flush()的可靠性如何?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4522字,纯文字阅读大概需要7分钟。
内容图文
考虑这个(简化的)代码段:
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);
}
}
}
正如评论中所提到的,我愿意同意对象流的任何错误.但问题是我无法触及(再次,它只是有时,它是非常随机的……)CommandThread的run().因此,除非我遗漏了其他内容,否则Object Streams无法导致这种失败.
编辑2:更正:它不接受()我无法达到,这是第一次读取操作:
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时,我已经有了一些协议“死锁”,因为创建Writer / Reader对ObjectStreams意味着一种握手,在混合这些流时可能会失败.
编辑:在再次阅读你的问题时,我意识到我没有回答.所以,是的,它是可靠的.和EJP答案1.
内容总结
以上是互联网集市为您收集整理的java – socket流的flush()的可靠性如何?全部内容,希望文章能够帮你解决java – socket流的flush()的可靠性如何?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。