我写了一个SocketClient
来连接套接字,并在其中添加一些回调。
public class SocketClientV2 {
public static void main(String[] args) {
SocketClientV2.Listener listener = new SocketClientV2.Listener() {
@Override
public void recv(byte[] result) {
// TODO Auto-generated method stub
System.out.println("====recv something");
}
@Override
public void connected() {
// TODO Auto-generated method stub
System.out.println("=====connected!");
}
@Override
public void disconnect() {
// TODO Auto-generated method stub
System.out.println("=====disconnect!");
}
};
SocketClientV2 client = new SocketClientV2("172.16.16.102", 4444,
10000, listener);
byte[] test = new byte[10];
test[0] = (byte) 0x1c;
test[1] = (byte) 0xff;
test[2] = (byte) 0x08;
client.send(test);
}
public interface Listener {
public void recv(byte[] result);
public void connected();
public void disconnect();
}
Socket client = null;
boolean isConnect = false;
OutputStream outputStream = null;
InputStream inputStream = null;
public SocketClientV2() {
}
Listener cb = null;
public SocketClientV2(String site, int port, int timeout, Listener cb) {
this.cb = cb;
try {
client = new Socket(site, port);
client.setSoTimeout(timeout);
System.out.println("Client is created! site:" + site + " port:"
+ port);
if (isConnected()) {
isConnect = true;
if (cb != null) {
cb.connected();
}
checkConnect();
listenRecv();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getClient() {
return this.client;
}
public void closeSocket() {
try {
isConnect = false;
inputStream.close();
outputStream.close();
client.close();
client = null;
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isConnected() {
try {
client.sendUrgentData(0xff);
isConnect = true;
} catch (Exception e) {
System.out.println("return false....2");
isConnect = false;
e.printStackTrace();
return false;
}
return true;
}
private void checkConnect() {
new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("check connect....1");
try {
while (isConnected()) {
Thread.sleep(500);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("finally....3");
if (cb != null) {
cb.disconnect();
}
closeSocket();
}
}
}.start();
}
private void listenRecv() {
new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("listening Recv....");
try {
inputStream = client.getInputStream();
while (isConnect) {
byte[] result = readStream(inputStream);
if (cb != null) {
cb.recv(result);
}
Thread.sleep(500);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
public void send(final byte[] byteSend) {
new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
// System.out.println("sendMsg coming....");
if (isConnect) {
try {
outputStream = client.getOutputStream();
outputStream.write(byteSend);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
public byte[] readStream(InputStream inStream) throws Exception {
int count = 0;
while (count == 0) {
// System.out.println(0);
count = inStream.available();
// if(count!=0)
// System.out.println(count);
}
byte[] b = new byte[count];
inStream.read(b);
return b;
}
}
有一个线程checkConnect
来检查套接字的连接状态..
但运行几分钟后会断开连接,
Client is created! site:172.16.16.102 port:4444
=====connected!
check connect....1
listening Recv....
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
return false....2
java.io.IOException: Broken pipe
at java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:622)
at java.net.Socket.sendUrgentData(Socket.java:954)
at com.udpdemo.multicast.SocketClientV2.isConnected(SocketClientV2.java:100)
at com.udpdemo.multicast.SocketClientV2.access$0(SocketClientV2.java:98)
finally....3
=====disconnect!
at com.udpdemo.multicast.SocketClientV2$2.run(SocketClientV2.java:121)
java.io.IOException: Stream closed.
at java.net.PlainSocketImpl.available(PlainSocketImpl.java:483)
at java.net.SocketInputStream.available(SocketInputStream.java:217)
at com.udpdemo.multicast.SocketClientV2.readStream(SocketClientV2.java:205)
at com.udpdemo.multicast.SocketClientV2$3.run(SocketClientV2.java:154)
以及sendUrgentData
???
答案 0 :(得分:1)
'断管'始终意味着您写入了已被对等方关闭的连接。这是一个应用程序协议错误。
但是除非这个客户端的对等方没有用Java编写,否则首先使用紧急数据是没有意义的。 Java只能在线接收紧急数据,即在已经发送的所有其他待处理数据之后。只有当对等方呼叫setOOBLine(true)时才会发生这种情况,否则就会发生
默认情况下,此选项被禁用,并且套接字上收到的TCP紧急数据将被静默丢弃。
您可以通过检测断开连接来执行此操作。在这种情况下,你的梦想成真,它的工作,你所要做的就是相应地调整你的捕获和你的代码。但这通常不是一种可靠的技术。
其他说明:
isConnected()
在创建Socket,
之后测试它时永远不会是假的,之后它永远不会变得虚假。您需要重新访问所有调用此方法的代码。其中大部分都没有意义,或者依赖于错误的假设。readStream()
返回零时,您的available()
方法旋转循环。这绝对没有意义。你只是在吸CPU。它也与您尝试使用读取超时完全不一致,当这个循环存在时,它根本无法工作。以下read()
调用将阻塞,直到至少一个字节的数据到达,或者流结束或发生异常。您现在的代码永远不会检测到流的结尾。您还需要完全重新设计这部分代码。例如,返回字节数组的做法很糟糕。read().
返回的计数。永远不要这样做。