错误信息
```java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.net.SocketInputStream.read(SocketInputStream.java:90)
at test.UserSocket.run(UserSocket.java:43)
java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.net.SocketInputStream.read(SocketInputStream.java:90)
at test.UserSocket.run(UserSocket.java:43)
这是一个WebScoket 的小测试。我开了3个浏览器测试正常后,关闭其中一个就会这个异常以下是我的代码麻烦各位大神给看看
package test;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import sun.applet.Main;
public class ServerSocketTest {
public static List clientSocket = new ArrayList();
public ServerSocketTest() throws IOException{
ServerSocket ss = new ServerSocket(30000);
System.out.println("服务器启动等待客户端连接");
while(true){
Socket s =ss.accept();//等待客户端连接
clientSocket.add(s);
System.out.println("客户端总人数"+clientSocket.size());
//为新用户启动线程
new UserSocket(s).start();
}
}
public static void main(String[] args) throws IOException {
new ServerSocketTest();
}
}
下面是线程代码
package test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.misc.BASE64Encoder;
public class UserSocket extends Thread{
private Socket socket;
public UserSocket(Socket socke){
this.socket = socke;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();//获取用户输入流
OutputStream ops = socket.getOutputStream();//获取用户输出流
byte[] buff = new byte[1024];//字节
String red = ""; //用了存放客户端请求过来的内容(客户端信息)
// 读取数据,此时建立与wabSocket的握手
int count = is.read(buff);//读取客户端请求内容的长度
if(count > 0){
//客户端请求数据转化字符串
red = new String(buff,0,count);
//获取WebSocket的值
String seckey = getSecWebSocketKey(red);
String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: "
+ "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "
+ getSecWebSocketAccept(seckey) + "\r\n\r\n";
//推送向客户端
ops.write(response.getBytes("utf-8"));
int hasRedad = 0;
// 不断读取WebSocket发送过来的数据
System.out.println("while循环前,等待前端推送数据。。。。。。。。。。。。");
while((hasRedad = is.read(buff))>0){//判断循环读取
System.out.println("后台接收到值,进入While循环处理");
/*
* 因为WebSocket发送过来的数据遁寻了一定的协议格式, 其中第3~6个字节是数据掩码,
* 从第七个字节开始才是真正的有效数据。 因此程序使用第3~6个字节对后面的数据进行了处理
*/
for (int i = 0; i < hasRedad - 6; i++) {
buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]);
}
//获得从浏览器发送过来的数据
String pushMsg = new String(buff,6,hasRedad - 6, "utf-8");//第一个值要读取的字节,从第几个开始读取,字符串的总长度,字符集
//便利Socket集合,向每个Socket对象发送信息
for (Iterator<Socket> it = ServerSocketTest.clientSocket.iterator();it.hasNext(); ) {
try {
Socket s = it.next();
byte[] pushHead = new byte[2];
pushHead[0] = buff[0];
pushHead[1] = (byte) pushMsg.getBytes("utf-8").length;
//发送前两个字节
s.getOutputStream().write(pushHead);
//发送有效数据
s.getOutputStream().write(pushMsg.getBytes("utf-8"));
} catch (SocketException e) {
//如果捕获到异常将其从集合中删除
// 如果捕捉到异常,表明该Socket已经关闭
it.remove();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 获取WebSocket请求的Seckey
private String getSecWebSocketKey(String req) {
// 构建正则表达式,获取Sec-WebSocket-Key:后面的内容
Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
Matcher m = p.matcher(req);
if (m.find()) {
// 提取Sec-WebSocket-Key
String foundstring = m.group();
return foundstring.split(":")[1].trim();
} else {
return null;
}
}
// 根据WebSocket请求的Seckey计算SecAccept
private String getSecWebSocketAccept(String key) throws Exception {
String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
key += guid;
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(key.getBytes("ISO-8859-1"), 0, key.length());
byte[] shalHash = md.digest();
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(shalHash);
}
}
刚才又调试了几次,发现了一些新的东西。
同时开启多个页面进行程序测试。当其中一个页面关闭时,这个页面向后台发送了一条数据,后台接收后处理并发送给其他页面。但是这个页面关闭了,本线程下发送给其他页面的信息全部发送失败。由于发送信息发送不出去,本线程就在此处
} catch (SocketException e) {
//如果捕获到异常将其从集合中删除
// 如果捕捉到异常,表明该Socket已经关闭
it.remove();
}
把其他的Socket对象全部删除了,导致所有的Socket对象连接都断开了。求教大神们有没有什么靠谱的解决办法