作为最近一个问题的后续内容,我想知道为什么在没有尝试在TCP套接字上进行读/写操作的情况下,为什么Java不可能检测到套接字已被对等端正常关闭?无论是使用前NIO Socket还是NIO ,情况似乎都是如此SocketChannel.
当对等体正常关闭TCP连接时,连接两端的TCP堆栈都知道这一事实.服务器端(启动关闭的那个)最终处于状态FIN_WAIT2,而客户端(未明确响应关闭的那个)最终处于状态CLOSE_WAIT.为什么没有一个方法Socket或SocketChannel可以查询TCP堆栈看到底层的TCP连接是否已经终止?是不是TCP堆栈没有提供这样的状态信息?或者这是一个设计决定,以避免昂贵的内核调用?
在已经发布了这个问题的答案的用户的帮助下,我想我会看到问题可能来自哪里.未明确关闭连接的一方最终处于TCP状态,CLOSE_WAIT这意味着连接正在关闭并等待一方发出自己的CLOSE操作.我认为isConnected返回true和isClosed返回是公平的false,但为什么不存在类似的东西isClosing呢?
以下是使用pre-NIO套接字的测试类.但使用NIO可获得相同的结果.
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(12345);
final Socket cs = ss.accept();
System.out.println("Accepted connection");
Thread.sleep(5000);
cs.close();
System.out.println("Closed connection");
ss.close();
Thread.sleep(100000);
}
}
import java.net.Socket;
public class MyClient {
public static …Run Code Online (Sandbox Code Playgroud) 我遇到了Java套接字API的一些问题.我正在尝试显示当前连接到我的游戏的玩家数量.很容易确定玩家何时连接.但是,确定玩家何时使用套接字API断开连接似乎不必要.
调用isConnected()已远程断开的套接字似乎总是返回true.同样,调用isClosed()已远程关闭的套接字似乎总是返回false.我已经读过,要实际确定套接字是否已关闭,必须将数据写入输出流并且必须捕获异常.这似乎是处理这种情况的一种非常不洁净的方式.我们不得不经常通过网络垃圾邮件垃圾邮件,以便知道套接字何时关闭.
还有其他解决方案吗?
我试图找出Java TCP套接字当前是否已连接,以下似乎只是告诉我套接字是否已经连接 - 而不是它当前是否仍然连接.
socket.isConnected();
Run Code Online (Sandbox Code Playgroud)
任何帮助表示感谢,谢谢.
我的应用程序从手机收集数据并将其发送到远程服务器.
数据首先存储在内存中(或者当文件足够大时存储在文件中),每隔X秒左右,应用程序就会刷新该数据并将其发送到服务器.
关键是每一条数据都成功发送,我宁愿发送两次数据而不是发送数据.
作为测试,我将应用程序设置为每5秒发送一个带有时间戳的数据,这意味着服务器上每5秒出现一个新行.
如果我杀了服务器,我希望线路停止,现在应该将它们写入内存.
当我再次启用服务器时,我应该能够确认没有任何事件丢失.
然而问题是,当我杀死服务器时,IO操作开始失败大约需要20秒,这意味着在这20秒内,应用程序会愉快地发送事件并将其从内存中删除,但它们永远不会到达服务器并永远丢失.
我需要一种方法来确保数据实际到达服务器.
这可能是最基本的TCP问题之一,但并非如此,我还没有找到任何解决方案.
Socket.setTcpNoDelay(true)OutputStream直接我无法改变服务器如何响应意味着我无法告诉服务器确认数据(不仅仅是TCP的机制),服务器只是默默地接受数据而不发回任何东西.
课程初始化:
socket = new Socket(host, port);
socket.setTcpNoDelay(true);
Run Code Online (Sandbox Code Playgroud)
数据发送的位置:
while(!dataList.isEmpty()) {
String data = dataList.removeFirst();
inMemoryCount -= data.length();
try {
OutputStream os = socket.getOutputStream();
os.write(data.getBytes());
os.flush();
}
catch(IOException e) {
inMemoryCount += data.length();
dataList.addFirst(data);
socket = null;
return false;
}
}
return true;
Run Code Online (Sandbox Code Playgroud)
我再说一遍,我无法改变服务器的行为方式.
它通过TCP和UPD接收数据,并且不会发送任何数据以确认接收.这是一个事实,并且在一个完美的世界中,服务器会确认数据,但这根本不会发生.
Fraggle发布的解决方案非常完美(关闭套接字并等待输入流关闭).
然而,这带来了一系列新问题.
由于我在手机上,我必须假设用户无法发送无限量的字节,并且我希望尽可能将所有数据流量保持在最低限度.
我不担心打开一个新套接字的开销,这几个字节不会有所作为.然而,我担心的是,每次我连接到服务器时,我都必须发送一个短字符串来标识我是谁.
字符串本身不是那么长(大约30个字符)但如果我经常关闭并打开套接字会增加.
一种解决方案只是每隔X字节"刷新"一次数据,问题是我必须明智地选择X; 如果太大,如果套接字发生故障,将发送过多的重复数据,如果它太小,则开销太大.
我的最终解决方案是通过每X字节关闭它来"刷新"套接字,如果一切都不顺利,那么X字节将再次发送.
这可能会在服务器上创建一些重复事件,但可以在那里进行过滤.
我正在使用循环从交流Berkeley套接字读取消息,但我无法检测套接字何时断开连接,所以我接受新的连接.请帮忙
while(true) {
bzero(buffer,256);
n = read(newsockfd,buffer,255);
printf("%s\n",buffer);
}
Run Code Online (Sandbox Code Playgroud) 我会假设调用isConnected()套接字会告诉我是否连接到另一端.
返回:如果套接字成功连接到服务器,则返回true
但经过检查然后调用flush()我得到的套接字
java.net.SocketException:管道损坏
怎么isConnected比不同isClosed,什么是每一个真正的行为?
如何在不向流写入任何内容或创建新连接的情况下正式关闭另一方?还有办法吗?
你们建议使用9针电缆中的哪个信号/针来检查连接状态?
到目前为止,我正在使用DSR信号,因为在硬件测试中,如果电缆正确连接,则如果断开连接,则DSR信号为1,DSR变为0。但是,与其他驱动程序和/或操作系统相比,DSR在消息传输过程中会发生变化或始终为0。因此,除非在晴天在25ºC的受控条件下,否则我认为此DSR信号并不可靠。
那么如何在给定的时间点知道我是否仍在连接,即电缆没有断开?
请注意,连接可能会丢失,并且我的串行端口仍然存在并且已在操作系统的端口列表中打开,因此检查端口是否存在无法解决任何问题。我唯一的希望是依靠9个引脚之一进行检查。
另外,我也不想发送或接收字节来检查连接状态。应该有更好的方法...
谢谢!